От автора: на прошлой неделе мне представилась возможность поработать над побочным проектом, который не планируется включать в матрицу поддержки Internet Explorer 11, и это вызвало у меня только положительные эмоции! Это открывает дверь к большому количеству забавного CSS, под названием «Специальные возможности».
Добавление соответствующей «Темной темы» в приложение некоторое время ожидало своей очереди, и, увидев в моем графике немного свободного времени, я сел, чтобы придумать это. В этом нет ничего сверх оригинального, но я остановился на решении, в котором я смогу наложить несколько слоев на возможность тематического оформления своего приложения, и при этом сохранить некоторую мощь Sass.
Существующий проект использовал Sass для неполных повторений, вложений, переменных, карт и циклов for для создания некоторых служебных классов. Цветовые переменные настраиваются следующим образом:
// Sass Vars $black: #1f1f1f; $grey: #656565; $light-grey: #f2f2f2; $white: #ffffff; $primary: #e95a26;
Преобразовать это в пользовательские свойства CSS было довольно просто:
// Custom Properties html { --black: #{$black}; --grey: #{$grey}; --light-grey: #{$light-grey}; --white: #{$white}; --primary: #{$primary}; }
Использование переменных Sass здесь почти излишне, но я рад, что не удалил их. Покопавшись в коде, я нашел десятки мест, где мы использовали цветовые функции Sass, такие как lighten() и darken(). Программная генерация цветов (серого) по-прежнему имеет большое значение для этого проекта. К сожалению, в CSS нет цветовых функций (пока). Вместо того, чтобы позволить этому стать для меня препятствием, я решил, что могу взять лучшее из обоих миров.
--border: #{darken($light-grey, 6%)};
После создания переменных для моей светлой темы по умолчанию, я начал создавать темный режим. В итоге мы использовали для этого переключатель JavaScript в пользовательском интерфейсе, но на первом этапе я начал с медиа-запроса prefers-color-scheme и использовал панель рендеринга Dev Tools, чтобы переключить его.
@media (prefers-color-scheme: dark) { html { --black: #{$white}; // BIG NOPE --white: #{$black}; // BIGGER NOPE } }
Стоп. Это не очень хорошо. Нарушение значения слов — признак плохой стратегии тематики, и я потеряю понимание реальности. Зная, что это плохой путь, имеет смысл ввести уровень абстракции над моими переменными CSS с семантическими именами, которые работают как в светлых, так и в темных темах.
Конечный результат выглядит примерно так, когда все переменные Sass, CSS и темы объединены:
html { // Theme Vars --heavy-text: var(--black); --faint-text: var(--grey); --bg-alt: var(--light-grey); --bg: var(--white); --border: #{darken($light-grey, 6%)}; @media (prefers-color-scheme: dark) { --heavy-text: var(--white); --faint-text: var(--light-grey); --bg-alt: #{lighten($black, 6%)}; --bg: var(--black); --border: #{darken($grey, 6%)}; } }
Иногда я хочу применить противоположный цвет в темном режиме. В других случаях я хочу найти что-то совершенно другое, вот где доступ к этим цветовым функциям очень помогает. Я могу поддерживать базовую цветовую палитру, но при необходимости адаптировать ее.
Остальная часть работы заключалась в прочесывании приложения и выполнении поиска и замены по всему документу. $black заменил на var(—heavy-text), $white стал var(—bg) и так далее. Через пару часов мое светлое приложение теперь поддерживает темный режим. С точки зрения обратной совместимости, все переменные Sass по-прежнему работают. Если есть существующая работа в ветке или какая-то жестко заданная переменная Sass, которую я пропустил при миграции, в светлой теме по умолчанию ничего не сломается. Этот многоуровневый подход с переменными имеет некоторую встроенную устойчивость, когда мы по-прежнему сохраняем мощность существующих инструментов, но немного уменьшаем зависимость от них, не разрушая при этом все приложение.
Заключение
Некоторые краткие выводы из этого небольшого упражнения по добавлению тем в существующее приложение за пару часов:
Я рад, что мы начали с буквальных имен переменных в Sass. Я знаю, что использование семантических имен переменных, например, $brand-primary сейчас в тренде, и я отстаивал их раньше, но помогло то, что у нас не было этой абстракции до тех пор, пока она нам не понадобилась на уровне тем.
Ограничить настраиваемость — тяжелая работа. Старайтесь внедрять все в меру, и не переусердствуйте. Для каждой переменной, которую вы используете сейчас, у вас будет столько же проблем, сколько позже настраиваемых контекстов.
Мы хорошо ознакомились с полудюжиной переменных. Можно еще добавить определенное их количество, но немного. Я думаю, что главное — установить ограничения на то, сколько оттенков серого вы используете.
Удачный подход в использовании переменных CSS для всего этого заключается в том, что вы можете переопределять вещи на уровне компонентов. Если —bg-alt в обеих темах неправильный цвет, или вам нужен какой-то особый неуказанный цвет на сингапурский Новый год, или —bg-alt находится поверх —bg-alt… вы можете изменить его. Определенные переменные поддерживаются слабо. Каскад имеет приоритет.
Самый важный вывод для меня заключается в том, что я еще не закончил с Sass. Мне нравится Sass. Я использую его с большой выгодой хотя бы потому, что приходится использовать на один инструмент сборки меньше. И если CSS получит функции цвета, я думаю, мы будем намного ближе к идеальным стилям без использования Sass.
Автор: Dave Rupert
Источник: daverupert.com
Редакция: Команда webformyself.