Организация SCSS: цвета
Удобно в SCSS сделать переменные для основных цветов приложения (палитра), и потом использовать везде понятные названия, вместо кодов цветов. Статья описывает современный универсальный и гибкий способ организации с работы с цветами, основанный на модулях и @use вместо устаревшего @import.
Для начала опишу как примерно выглядит “старый” подход. Создается файл _variables.scss
и в нем определяется куча переменных на все случаи жизни, в том числе и переменные для цветов:
// _variables.scss ... // Colors $color-primary: #6750A4; $color-background: #EADDFF; ...
Далее, в корневой SCSS-файл (entry-point-файл) сначала импортируется этот файл с переменными, а затем файлы с различными компонентами:
// styles.scss @import './variables'; @import './my-component'; @import './other-component'; ...
При импорте все переменные становятся глобальными и их напрямую можно использовать в других файлах, например так:
// _my-component.scss .my-component { color: $color-primary; background-color: $color-background; }
Примерно такой подход я встречал на большинстве проектов. Например, Bootstrap все еще использует такой подход – https://github.com/twbs/bootstrap/blob/main/scss/_variables.scss
В целом, схема рабочая. Но мне не нравится этот огромный файл с переменными. И не нравится что все переменные глобальные.
Другой подход я подсмотрел в реализации Material Components for the web. И теперь на всех проектах использую только его. Здесь нет единого огромного файла _variables.scss. Вместо этого переменные располагаются контекстно, рядом с модулями, к которым они относятся.
Организауем все цвета приложения в виде модуля colors:
// theme/_colors.scss $primary: #01579B !default; $background: #E1F5FE !default;
Кстати, так как переменные уже не будут глобальными, можно использовать более простые и короткие имена, не опасаясь что они совпадут с какими-то другими переменными из других файлов. Я предпочитаю класть этот модуль в папку theme, позже объясню зачем.
Далее, в файле, в котором нужны цвета, подключаем этот модуль и используем переменные с указанием модуля:
// _my-component.scss @use './theme/colors'; .my-component { color: colors.$primary; background-color: colors.$background; }
Да, модуль цветов нужно подключать в каждом файле, которому нужны цвета, вместо одного подключения как в предыдущем методе. Но, зато такой подход дает большую… модульность:
- Теперь нет одного огромного файла
_variables.scss
со всеми переменными. Соответственно код уже не монолит, а набор связанных модулей. - Сразу понятно от каких других модулей зивисит данный конкретный файл (компонент).
- Переменные используются с префиксом (namespace), по которому видно из какого именно модуля пришла та или иная переменная.
Бонус: поддержка нескольких тем (themes)
Допустим, у приложения есть две темы: обычная и контрастная.
Делаем для них соответствующие подпапки в папке theme. И добавляем в каждую по _index.scss
:
В theme/default-theme/_index.scss
подключаем все тот же модуль colors
, который лежит папкой выше. Но подключаем с переопределением значений переменных в модуле, тоесть устанавливаем цвета для обычной темы:
// theme/default-theme/_index.scss @use '../colors' with ( $primary: #006783, $background: #bde9ff );
А в контрастной, например, устанавливаем цвета с большим уровнем контрастности:
// theme/contrast-theme/_index.scss @use '../colors' with ( $primary: #000000, $background: #ffffff );
Важно понимать – команда @use
загружает модуль только один раз, когда встречает его первый раз. Поэтому нужно что бы самым первым встретился @use colors, который настраивает цвета для данной темы. Все последующие @use colors, которые будут встречаться в файлах компонентов, будут использовать эти переопределенные цвета.
Для каждой темы нужен будет отдельный entry-point-файл. В начале такого файла подключаем тему:
// styles-default.scss // В самом начале файла подключаем нужную тему, которая настроит цвета в colors. @use './theme/normal-theme'; // Далее подключаем весь остальной код, который будет общий для обоих тем @use './my-component';
// styles-contrast.scss // В самом начале файла подключаем нужную тему, которая настроит цвета в colors. @use './theme/contrast-theme'; // Далее подключаем весь остальной код, который будет общий для обоих тем @use './my-component';
Способ использования этих тем уже зависит от конкретного приложения. Можно например сгенерить отдельные CSS-файлы и переключаться между ними.