{"id":13937,"url":"\/distributions\/13937\/click?bit=1&hash=d7d14c3b8af3dcecd31f9c8dffe4a50332e4ebbfcbdd99100d80038cd6e8d92f","title":"\u041f\u043e \u043a\u0430\u043a\u0438\u043c \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430\u0434 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c \u0432 \u043e\u043d\u043b\u0430\u0439\u043d-\u0431\u0430\u043d\u043a\u0430\u0445","buttonText":"\u0423\u0437\u043d\u0430\u0442\u044c","imageUuid":"21006007-5738-582d-b5cb-54da5b558308"}

Смена темы сайта через CSS-переменные

Всем привет. Меня зовут Петр Цой. Я нахожусь в поисках своей первой работы в качестве ReactJS разработчика. Есть хороший опыт самостоятельной разработки коммерческих сайтов. В качестве примера и моего резюме выступает одноименный сайт petrtcoi.com. Ссылка на GitHub.

Если вам нужен начинающий специалист, пишите!

На сайте сейчас кот. В ближайшее время сделаю приличную фотографию и размещу ее.

Почему CSS

Возможность переключать сайт между разными цветовыми схемами подразумевает возможность динамически менять стили большинства его компонентов. В минимальном варианте - это цвет текста и цвет заднего фона.

Если округлить, то добиться этого можно двумя путями:

  • через JavaScript, меняя свойства соответствующих переменных;
  • через CSS, меняя значения CSS-переменных;

Первый вариант требует перерисовки всех компонентов, связанных с новой темой. Это может негативно сказаться на производительности. К тому же, здесь потребуется дополнительная настройка проекта, так как свойства новой темы нужно передавать всем компонентам сайта.

Второй вариант не имеет данного недостатка. Мы просто меняем значения CSS-переменных, отвечающих за отображение темы, и обновление сайта происходит в автоматическом режиме без перерисовки каких-либо компонентов. Этот способ не только быстрее, но и проще в реализации.

На скриншоте ниже показан результат смены темы на моем сайте.

Внизу можно заметить, что один компонент все же переписывался - это собственно сам Switcher, который меняет тему.

Настройка темы через CSS

Для реализации данной возможности я вынес переменные, связанные с темой в отдельный файл.

/* src/theme/theme.css */ :root { --color-text-main: #bab7b7; --background: #1b1b1b; --change-theme-duration: 0.5s; } [data-theme="light"] { --color-text-main: #1b1b1b; --background: white; }

Здесь заданы переменные для цвета текста и заднего фона. В базовом варианте - для темной темы, ниже - для светлой темы "light".

Для красоты также добавлена характеристика --change-theme-duration: 0.5s;, чтобы цвета менялись не мгновенно, но с небольшой задержкой.

Рядом, в этой же папке, разместим вспомогательный файл со списком возможных тем. У нас их две.

// src/theme/theme.enum.ts export enum Theme { light = 'light', dark = 'dark' }

Далее CSS-переменные темы прописываются в файле с глобальными стилями.

/* src/css/globals.css */ html, body { /* другие стили */ color: var(--color-text-main); background-color: var(--background); transition: background-color var(--change-theme-duration); }

Готово!

Все, что теперь требуется, так это повесить на наш компонент <ThemeSwitcher /> обработчик, который будет устанавливать на корневой элемент требуемый нам атрибут.

Результат.

Подводные камни. Часть 1.

Подобная реализация смены темы размывает зону ответственности. Получается, что часть логики приложения продолжает обрабатываться через JavaScript, а какая-то часть - уже через CSS. Возможно это создаст некоторые трудности при дальнейшем росте проекта. Тем более, если злоупотреблять данным приемом.

С другой стороны, этот метод слишком эффективен, чтобы можно было им пренебречь. Думаю, достаточно будет выполнить следующего:

  • Позже к проекту подключу Redux и подобные "глобальные" эффекты будут проводить через него. Все будет аккуратно лежать в одном месте и, по крайней мере, будет просто найти нужный участок кода.
  • Подобные CSS-трюки постараюсь ограничить рамками отдельных элементов.

Подводные камни. Часть 2.

Главное преимущество CSS-подхода привело и к сложности его тестирования. Так как стандартная библиотека для unit-тестов @testing-library попросту не "видит", какие именно параметры скрыты за названиями классов, то она и не в состоянии проверить, какой цвет установлен у элемента, находится ли он в зоне видимости и т.д.

В итоге, для тестирования смены темы я использовал e2e тестирование с помощью Playwright. Это не так удобно, как быстрые unit-тесты, но работает.

Подробнее про тестирование напишу в своей следующей записи.Спасибо за внимание.

0
Комментарии
Читать все 0 комментариев
null