Смена темы сайта через CSS-переменные
Всем привет. Меня зовут Петр Цой. Я нахожусь в поисках своей первой работы в качестве ReactJS разработчика. Есть хороший опыт самостоятельной разработки коммерческих сайтов. В качестве примера и моего резюме выступает одноименный сайт petrtcoi.com. Ссылка на GitHub.
Если вам нужен начинающий специалист, пишите!
На сайте сейчас кот. В ближайшее время сделаю приличную фотографию и размещу ее.
Почему CSS
Возможность переключать сайт между разными цветовыми схемами подразумевает возможность динамически менять стили большинства его компонентов. В минимальном варианте - это цвет текста и цвет заднего фона.
Если округлить, то добиться этого можно двумя путями:
- через JavaScript, меняя свойства соответствующих переменных;
- через CSS, меняя значения CSS-переменных;
Первый вариант требует перерисовки всех компонентов, связанных с новой темой. Это может негативно сказаться на производительности. К тому же, здесь потребуется дополнительная настройка проекта, так как свойства новой темы нужно передавать всем компонентам сайта.
Второй вариант не имеет данного недостатка. Мы просто меняем значения CSS-переменных, отвечающих за отображение темы, и обновление сайта происходит в автоматическом режиме без перерисовки каких-либо компонентов. Этот способ не только быстрее, но и проще в реализации.
На скриншоте ниже показан результат смены темы на моем сайте.
Настройка темы через CSS
Для реализации данной возможности я вынес переменные, связанные с темой в отдельный файл.
Здесь заданы переменные для цвета текста и заднего фона. В базовом варианте - для темной темы, ниже - для светлой темы "light".
Для красоты также добавлена характеристика --change-theme-duration: 0.5s;, чтобы цвета менялись не мгновенно, но с небольшой задержкой.
Рядом, в этой же папке, разместим вспомогательный файл со списком возможных тем. У нас их две.
Далее CSS-переменные темы прописываются в файле с глобальными стилями.
Готово!
Все, что теперь требуется, так это повесить на наш компонент <ThemeSwitcher /> обработчик, который будет устанавливать на корневой элемент требуемый нам атрибут.
Результат.
Подводные камни. Часть 1.
Подобная реализация смены темы размывает зону ответственности. Получается, что часть логики приложения продолжает обрабатываться через JavaScript, а какая-то часть - уже через CSS. Возможно это создаст некоторые трудности при дальнейшем росте проекта. Тем более, если злоупотреблять данным приемом.
С другой стороны, этот метод слишком эффективен, чтобы можно было им пренебречь. Думаю, достаточно будет выполнить следующего:
- Позже к проекту подключу Redux и подобные "глобальные" эффекты будут проводить через него. Все будет аккуратно лежать в одном месте и, по крайней мере, будет просто найти нужный участок кода.
- Подобные CSS-трюки постараюсь ограничить рамками отдельных элементов.
Подводные камни. Часть 2.
Главное преимущество CSS-подхода привело и к сложности его тестирования. Так как стандартная библиотека для unit-тестов @testing-library попросту не "видит", какие именно параметры скрыты за названиями классов, то она и не в состоянии проверить, какой цвет установлен у элемента, находится ли он в зоне видимости и т.д.
В итоге, для тестирования смены темы я использовал e2e тестирование с помощью Playwright. Это не так удобно, как быстрые unit-тесты, но работает.
Подробнее про тестирование напишу в своей следующей записи.Спасибо за внимание.