Как объединить функции цветов SASS и CSS-переменные

Как объединить функции цветов SASS и CSS-переменные

От автора: новый метод, поддерживаемый во всех браузерах, для сохранения в CSS-переменных цветов и изменения их с помощью функций SASS. Переменные CSS великолепны. Мы все это знаем. Значения цветов HSL лучшие. Согласна! Функции цветов SASS потрясающи. Да, естественно. Но как совместить все эти вещи и использовать их СЕГОДНЯ? Способ есть!

Мы разработали новый метод для нашего фреймворка, который сочетает в себе гибкость нативных переменных (хранящих значения цвета HSL) с практичностью функций SASS. Впервые слышите о CodyHouse Framework?

Проблема

В нашем фреймворке мы используем CSS-переменные. Мы интегрировали модифицированную версию плагина postcss-css-variable, чтобы создать запасной вариант для браузеров, которые их не поддерживают. Мы предпочли CSS-переменные, а не переменные SASS, потому что вы можете перезаписать их значение в определенных контрольных точках (или использовать классы). Эта функция оказалась особенно полезной для разработки наших адаптивных систем отступов и типографики , а также цветовых тем.

Тем не менее, вот как мы определяли переменные цветов, когда запустили фреймворк (v 1.0.0):

: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 великолепны, потому что они делают интуитивно понятным создание цветовых вариаций. Просто измените значения оттенка, насыщенности и яркости. Числа легко читаются. Однако, когда мы начали работать с компонентами, мы поняли, что не существует простого способа установить альфа-значение для цвета:

.component { background-color: hsla(var(--color-primary), 0.2); // not working
}

Вы можете включить переменные CSS в миксины и функции SASS, но приведенный выше код вернет недопустимое значение. (—var (color) заменяется на hsl (x, x%, x%)). Как это исправить?

Тест № 1 — Использование цветовых модов CSS с плагином PostCSS

Сначала мы попробовали использовать нативные функции цветов CSS.

.component { background-color: color-mod(var(--color-primary) alpha(20%));
}

Они аккуратны, но часто не поддерживаются в основных браузерах. Мы попытались интегрировать несколько плагинов PostCSS, чтобы создать запасной вариант, но безуспешно. Мы продолжали получать ошибки, поэтому решили, что этот метод слишком ненадежен.

Тест № 2 — Установка переменных CSS для альфа-значений

Поскольку наша проблема заключалась в невозможности установить значения непрозрачности для цветов, подход номер два создавал переменные CSS для альфа-значений:

:root, [data-theme="default"] { --color-primary: hsl(220, 90%, 56%); --color-primary-a20: hsla(220, 90%, 56%, 0.2);
}

На уровне компонента вам нужно установить альфа-значение, применяя переменную альфа:

.component { background-color: var(--color-primary-a20);
}

Имейте в виду, что цель состояла в том, чтобы сохранить все значения цвета в одном файле _colors.scss, чтобы всю систему было легко обслуживать. Мы не могли просто использовать hsla на уровне компонентов. Хотя мы не были полностью уверены в правильности этого варианта, мы решили использовать его в первой версии фреймворка.

Новое решение — создание миксина SASS для устранения проблем с беспорядочностью цветов

Создание переменных для альфа-значений оказалось плохим решением по двум основным причинам:

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

Поскольку наша система основана на цветовых темах (цвета взаимозаменяемы), если вы создаете альфа-переменную для цвета, то должны сделать то же самое для всех остальных цветов.

Мы вернулись на круги своя. Вот процесс, который закончился тем, что мы считаем отличным решением: во-первых, мы попытались использовать миксин для определения альфа-значения. Для этого требуются 3 переменных миксинов: $property, $color-variable и $opacity. Мы будем использовать миксин так:

.component { @include alpha(background-color, --color-primary, 0.2);
}

Вот код миксина:

@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 переменные для каждого цвета:

: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:

.component { background-color: alpha(var(--color-primary), 0.2);
}

Вот код функции:

// 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: https://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:

@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:

: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 вы можете установить значение непрозрачности, используя альфа-функцию:

.component { background-color: alpha(var(--color-primary), 0.2); // it works
}

Это работает! Мы только что добавили обновление фреймворка (v 1.1.0), которое включает новые миксины и обновленный файл _colors.scss.

Использование этого метода для создания дополнительных функций цветов

Поскольку этот метод позволяет получить доступ и изменить значения оттенка, насыщенности, яркости и альфа-значения, вы можете создать функцию для каждого из них! Изменение яркости:

@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);
}

Изменение насыщенности:

@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

Источник: https://codyhouse.co

Редакция: Команда webformyself.