От автора: новый метод, поддерживаемый во всех браузерах, для сохранения в CSS-переменных цветов и изменения их с помощью функций SASS. Переменные CSS великолепны. Мы все это знаем. Значения цветов HSL лучшие. Согласна! Функции цветов SASS потрясающи. Да, естественно. Но как совместить все эти вещи и использовать их СЕГОДНЯ? Способ есть!
Мы разработали новый метод для нашего фреймворка, который сочетает в себе гибкость нативных переменных (хранящих значения цвета HSL) с практичностью функций SASS. Впервые слышите о CodyHouse Framework?
Проблема
В нашем фреймворке мы используем CSS-переменные. Мы интегрировали модифицированную версию плагина postcss-css-variable, чтобы создать запасной вариант для браузеров, которые их не поддерживают. Мы предпочли CSS-переменные, а не переменные SASS, потому что вы можете перезаписать их значение в определенных контрольных точках (или использовать классы). Эта функция оказалась особенно полезной для разработки наших адаптивных систем отступов и типографики , а также цветовых тем.
Тем не менее, вот как мы определяли переменные цветов, когда запустили фреймворк (v 1.0.0):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
:root, [data-theme="default"] { // main --color-primary-darker: hsl(220, 90%, 36%); --color-primary-dark: hsl(220, 90%, 46%); --color-primary: hsl(220, 90%, 56%); --color-primary-light: hsl(220, 90%, 66%); --color-primary-lighter: hsl(220, 90%, 76%); --color-primary-a20: hsla(220, 90%, 56%, 0.2); --color-accent-darker: hsl(355, 90%, 41%); --color-accent-dark: hsl(355, 90%, 51%); --color-accent: hsl(355, 90%, 61%); --color-accent-light: hsl(355, 90%, 71%); --color-accent-lighter: hsl(355, 90%, 81%); // color contrast --color-bg: hsl(0, 0%, 100%); --color-bg-a00: hsla(0, 0%, 100%, 0); --color-contrast-lower: hsl(0, 0%, 95%); --color-contrast-low: hsl(240, 1%, 83%); --color-contrast-medium: hsl(240, 1%, 48%); --color-contrast-high: hsl(240, 4%, 20%); --color-contrast-higher: hsl(240, 8%, 12%); --color-contrast-higher-a90: hsla(240, 8%, 12%, 0.9); // semantic --color-border: var(--color-contrast-low); // ... } |
Значения цвета HSL великолепны, потому что они делают интуитивно понятным создание цветовых вариаций. Просто измените значения оттенка, насыщенности и яркости. Числа легко читаются. Однако, когда мы начали работать с компонентами, мы поняли, что не существует простого способа установить альфа-значение для цвета:
1 2 3 |
.component { background-color: hsla(var(--color-primary), 0.2); // not working } |
Вы можете включить переменные CSS в миксины и функции SASS, но приведенный выше код вернет недопустимое значение. (—var (color) заменяется на hsl (x, x%, x%)). Как это исправить?
Тест № 1 — Использование цветовых модов CSS с плагином PostCSS
Сначала мы попробовали использовать нативные функции цветов CSS.
1 2 3 |
.component { background-color: color-mod(var(--color-primary) alpha(20%)); } |
Они аккуратны, но часто не поддерживаются в основных браузерах. Мы попытались интегрировать несколько плагинов PostCSS, чтобы создать запасной вариант, но безуспешно. Мы продолжали получать ошибки, поэтому решили, что этот метод слишком ненадежен.
Тест № 2 — Установка переменных CSS для альфа-значений
Поскольку наша проблема заключалась в невозможности установить значения непрозрачности для цветов, подход номер два создавал переменные CSS для альфа-значений:
1 2 3 4 |
:root, [data-theme="default"] { --color-primary: hsl(220, 90%, 56%); --color-primary-a20: hsla(220, 90%, 56%, 0.2); } |
На уровне компонента вам нужно установить альфа-значение, применяя переменную альфа:
1 2 3 |
.component { background-color: var(--color-primary-a20); } |
Имейте в виду, что цель состояла в том, чтобы сохранить все значения цвета в одном файле _colors.scss, чтобы всю систему было легко обслуживать. Мы не могли просто использовать hsla на уровне компонентов. Хотя мы не были полностью уверены в правильности этого варианта, мы решили использовать его в первой версии фреймворка.
Новое решение — создание миксина SASS для устранения проблем с беспорядочностью цветов
Создание переменных для альфа-значений оказалось плохим решением по двум основным причинам:
Если вы работаете на уровне компонентов, вам нужно переключаться на _colors.scss файл в любое время, когда вы хотите использовать другое альфа-значение для цвета.
Поскольку наша система основана на цветовых темах (цвета взаимозаменяемы), если вы создаете альфа-переменную для цвета, то должны сделать то же самое для всех остальных цветов.
Мы вернулись на круги своя. Вот процесс, который закончился тем, что мы считаем отличным решением: во-первых, мы попытались использовать миксин для определения альфа-значения. Для этого требуются 3 переменных миксинов: $property, $color-variable и $opacity. Мы будем использовать миксин так:
1 2 3 |
.component { @include alpha(background-color, --color-primary, 0.2); } |
Вот код миксина:
1 2 3 4 5 6 |
@mixin alpha($property, $color-variable, $opacity) { $color-variable-h: var(#{$color-variable+'-h'}); $color-variable-s: var(#{$color-variable+'-s'}); $color-variable-l: var(#{$color-variable+'-l'}); #{$property}: hsla($color-variable-h, $color-variable-s, $color-variable-l, $opacity); } |
Чтобы это работало, нам нужно было установить 3 переменные для каждого цвета:
1 2 3 4 5 6 |
:root, [data-theme="default"] { --color-primary: hsl(220, 90%, 56%); --color-primary-h: 220; --color-primary-s: 90%; --color-primary-l: 56%; } |
Где —color-name-hз — это начение оттенка, —color-name-s — это процент насыщенности и —color-name-l — это процент яркости (Нет, мы не хотим отказываться от значений цвета HSL). Все еще слишком сложно, но что-то уже вырисовывается.
В этот момент у нас возникла идея создать вместо миксина собственную альфа-функцию SASS. Это позволило бы нам написать более простое объявление CSS:
1 2 3 |
.component { background-color: alpha(var(--color-primary), 0.2); } |
Вот код функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// return css color variable with different opacity value @function alpha($color, $opacity){ $color: str-replace($color, 'var('); $color: str-replace($color, ')'); $color-h: var(#{$color+'-h'}); $color-s: var(#{$color+'-s'}); $color-l: var(#{$color+'-l'}); @return hsla($color-h, $color-s, $color-l, $opacity); } // replace substring with another string // credits: //css-tricks.com/snippets/sass/str-replace-function/ @function str-replace($string, $search, $replace: '') { $index: str-index($string, $search); @if $index { @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); } @return $string; } |
Уже лучше! Последнее, что нас беспокоило — это необходимость вручную создавать 3 дополнительные переменные для каждого цвета (оттенок, насыщенность, яркость). Это раздражает, потому что вам нужно обновлять значения этих переменных каждый раз, когда вы изменяете цвет.
В какой-то момент мы поняли, что можем использовать миксин SASS для определения каждого цвета, чтобы мы могли автоматически генерировать значения оттенков, насыщенности и яркости в CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@mixin defineColorHSL($color, $hue, $saturation, $lightness){ #{$color}: unquote("hsl(#{$hue}, #{$saturation}, #{$lightness})");#{$color}-h: #{$hue};#{$color}-s: #{$saturation};#{$color}-l: #{$lightness}; } :root, [data-theme="default"] { @include defineColorHSL(--color-primary, 220, 89%, 56%); @include defineColorHSL(--color-accent, 355, 90%, 61%); @include defineColorHSL(--color-black, 240, 8%, 12%); @include defineColorHSL(--color-white, 0, 0%, 100%); // color contrasts @include defineColorHSL(--color-bg, 0, 0%, 100%); @include defineColorHSL(--color-contrast-lower, 0, 0%, 95%); @include defineColorHSL(--color-contrast-low, 240, 1%, 83%); @include defineColorHSL(--color-contrast-medium, 240, 1%, 48%); @include defineColorHSL(--color-contrast-high, 240, 4%, 20%); @include defineColorHSL(--color-contrast-higher, 240, 8%, 12%); } |
Красота этого подхода заключается в том, что вы все равно объявляете цвета через синтаксис, который легко понять и который позволяет создавать цветовые вариации, изменяющие значения HSL:
1 2 3 4 5 6 7 |
:root, [data-theme="default"] { @include defineColorHSL(--color-primary-darker, 220, 90%, 36%); @include defineColorHSL(--color-primary-dark, 220, 90%, 46%); @include defineColorHSL(--color-primary, 220, 90%, 56%); @include defineColorHSL(--color-primary-light, 220, 90%, 66%); @include defineColorHSL(--color-primary-lighter, 220, 90%, 76%); } |
Как установить альфа-значения на уровне компонента
В SCSS вы можете установить значение непрозрачности, используя альфа-функцию:
1 2 3 |
.component { background-color: alpha(var(--color-primary), 0.2); // it works } |
Это работает! Мы только что добавили обновление фреймворка (v 1.1.0), которое включает новые миксины и обновленный файл _colors.scss.
Использование этого метода для создания дополнительных функций цветов
Поскольку этот метод позволяет получить доступ и изменить значения оттенка, насыщенности, яркости и альфа-значения, вы можете создать функцию для каждого из них! Изменение яркости:
1 2 3 4 5 6 7 8 9 10 11 12 |
@function lightness($color, $lightnessMultiplier){ $color: str-replace($color, 'var('); $color: str-replace($color, ')'); $color-h: var(#{$color+'-h'}); $color-s: var(#{$color+'-s'}); $color-l: var(#{$color+'-l'}); @return hsl($color-h, $color-s, calc(#{$color-l} * #{$lightnessMultiplier})); } .component { background-color: lightness(var(--color-primary), 1.2); } |
Изменение насыщенности:
1 2 3 4 5 6 7 8 9 10 11 12 |
@function saturation($color, $saturationMultiplier){ $color: str-replace($color, 'var('); $color: str-replace($color, ')'); $color-h: var(#{$color+'-h'}); $color-s: var(#{$color+'-s'}); $color-l: var(#{$color+'-l'}); @return hsl($color-h, calc(#{$color-s} * #{$saturationMultiplier}), $color-l); } .component { background-color: saturation(var(--color-primary), 1.2); } |
Заключение
Основная цель нашего фреймворка — упрощение процесса запуска веб-проекта. Мы чувствуем, что движемся к этой цели.
Автор: Claudia Romano
Источник: //codyhouse.co
Редакция: Команда webformyself.