На днях разработчик пользовательского интерфейса Александр Броудин спросил меня, как я буду использовать Sass для создания различных палитр, похожих на данную палитру, где будет меняться только основной цвет. Я люблю играть с цветами программным способом, поэтому я решил попробовать.
Допустим, у вас есть палитра, состоящая из 7 красноватых цветов. Возможно, вы создали палитру вручную в Photoshop или с помощью функций Sass. 4-й (средний) цвет является базовым, и в нем есть три светлых тона и три более темных.
Теперь вам нужен способ быстро создать похожую палитру из другого базового цвета. По сути, вам нужна другая коллекция цветов, в которой разница в яркости и насыщенности основного цвета и каждого цвета в палитре одинакова. Таким образом, если разница между самым светлым цветом и основным цветом, скажем, 28%, вы хотите, чтобы самый легкий цвет из всех палитр был на 28% светлее, чем основной цвет его собственной палитры.
Если мы создали первую палитру вручную и не знаем, какие цветовые манипуляции нужны для того, чтобы каждый цвет из палитры был из основного цвета, как мы могли бы сделать все палитры идентичными?
Примечание: в этой статье используются фрагменты кода из другой моей статьи , опубликованной мной на Sass Way.
Создание наших функций
Сначала нам нужно инициализировать палитру по умолчанию как глобальную переменную.
$base-palette: (
'base': #ff6351,
'colors': #cfdfe8 #bfb9c3 #cf9192 #ff6351 #bf413c #7f3128 #732c24
) !default;
Наша базовая палитра — это карта, состоящая из 2 клавиш: базового цвета и списка цветов. Первые три — это светлые тона, начиная с самых легких. Затем у вас снова базовый цвет, а затем темные тона, заканчивающиеся самыми темными.
Теперь, чтобы понять, почему мы собираемся делать то, что собираемся делать, мне нужно объяснить всю идею. Если вы читали мою статью в «Sass Way», ее будет легче понять, но на случай, если у вас не было возможности ее прочитать, позвольте мне прояснить это.
Мы рассчитаем цветовые различия . Разница в цвете — это карта операций, которую нужно применить к цвету А, чтобы получить цвет В. В нашем случае нам потребуется список различий в цвете, по одному на каждый цвет палитры. Каждый цветовой дифференциал будет операциями, применяемыми к цвету N, чтобы иметь основной цвет (или обратный, это не имеет значения).
Вот функция изменения цвета:
@function color-diff($a, $b) {
$sat: saturation($a) - saturation($b);
$lig: lightness($a) - lightness($b);
$fn-sat: if($sat > 0, 'desaturate', 'saturate');
$fn-lig: if($lig > 0, 'darken', 'lighten');
@return (
adjust-hue: -(hue($a) - hue($b)),
#{$fn-sat}: abs($sat),
#{$fn-lig}: abs($lig)
);
}
Функция color-diff
$a
$b
Отлично.
Далее нам нужна функция, которая запускает color-diff
$base-palette
@function palette-diff($palette) {
$base: map-get($palette, 'base');
$colors: map-get($palette, 'colors');
$diffs: ();
@each $color in $colors {
$diffs: append($diffs, color-diff($base, $color));
}
@return $diffs;
}
Все, что нам нужно сделать сейчас, это запустить его один раз, а затем сохранить его в глобальной переменной. Нет необходимости вычислять эти различия для каждой запущенной палитры, достаточно только одного раза:
$base-palette: (
'base': #FF6351,
'colors': #CFDFE8 #BFB9C3 #CF9192 #FF6351 #BF413C #7F3128 #732C24
) !default;
$palette-diff: palette-diff($base-palette);
/**
* Yields a list of 7 maps (diffs)
(
(adjust-hue: 195.3931deg, desaturate: 64.78873%, lighten: 20.19608%),
(adjust-hue: 269.7931deg, desaturate: 92.30769%, lighten: 8.62745%),
(adjust-hue: 352.82536deg, desaturate: 60.75949%, lighten: 3.13725%),
(adjust-hue: 0deg, saturate: 0%, lighten: 0%),
(adjust-hue: 0.20532deg, desaturate: 47.80876%, darken: 16.66667%),
(adjust-hue: 0deg, desaturate: 47.90419%, darken: 33.13725%),
(adjust-hue: -0.13095deg, desaturate: 47.68212%, darken: 36.27451%)
)
*/
Все идет нормально! Осталось только две функции. Первый из старой статьи, применяя diff (возврат color-diff
@function apply-diff($color, $diff) {
@each $function, $value in $diff {
$color: call($function, $color, $value);
}
@return $color;
}
Здесь мы применяем каждую функцию из diff к цвету, затем мы получаем другой цвет. Теперь нам нужна только функция, которая создает палитру из базового цвета. Давайте назовем это create-palette
@function create-palette($base-color) {
$palette: ();
@each $diff in $palette-diff {
$palette: append($palette, apply-diff($base-color, $diff));
}
@return $palette;
}
На данный момент, мы в основном сделали. Мы вызываем функцию create-palette
$base-palette
colors
Например:
$green-palette: create-palette(lightgreen);
// Returns: #f4f1f3 #d5d5d5 #c2cec0 lightgreen #79b079 #4f864f #497c49
Довольно аккуратно, а?
Делать вещи лучше
Список цветов — не самый лучший способ справиться с цветами. Что вы собираетесь использовать? nth($green-palette, 3)
Не очень практично. Что если мы превратили этот список в карту с явными ключами, такими как: lightest
lighter
light
base
dark
darker
darkest
Тогда вы можете сказать map-get($green-palette, light)
Для этого нет волшебства. Мы строим функцию, которая вручную превращает список цветов в карту:
@function palette($base-color) {
$colors: create-palette($base-color);
$keys: 'lightest' 'lighter' 'light' 'base' 'dark' 'darker' 'darkest';
$palette: ();
@for $i from 1 through min(length($colors), length($keys)) {
$palette: map-merge($palette, (nth($keys, $i): nth($colors, $i)));
}
@return $palette;
}
Наш предыдущий пример:
$green-palette: palette(lightgreen);
/**
* Yields
(
lightest: #f4f1f3,
lighter: #d5d5d5,
light: #c2cec0,
base: lightgreen,
dark: #79b079,
darker: #4f864f,
darkest: #497c49
)
*/
Довольно круто, правда?
Толкая вещи дальше
Вещи становятся вполне пригодными для использования, но ввод map-get(..., light)
Чтобы облегчить процесс (посмотрите, что я там делал?), Мы могли бы создать ряд помощников:
@function lightest($palette) {
@if not map-has-key($palette, 'lightest') {
@warn "`#{inspect($palette)}` doesn't seem to have a key named `lightest`.";
}
@return map-get($palette, 'lightest');
}
@function lighter($palette) {
@if not map-has-key($palette, 'lighter') {
@warn "`#{inspect($palette)}` doesn't seem to have a key named `lighter`.";
}
@return map-get($palette, 'lighter');
}
@function light($palette) {
@if not map-has-key($palette, 'light') {
@warn "`#{inspect($palette)}` doesn't seem to have a key named `light`.";
}
@return map-get($palette, 'light');
}
И так далее, вы получите картину. Тогда вы просто сделаете:
.el {
color: light($green-palette);
}
… Который можно представить как «светлый» цвет из $green-palette
.
Последние мысли
Как видите, мы можем многое сделать, чтобы упростить работу с цветами. Создание списков, карт и цветовых функций никогда не было проще.
Надеюсь, вам понравится идея. Ниже приведена демоверсия. Вы можете проверить это, отредактировав раздел «Палитры» в CSS, внизу. Изменение любого из шести цветов изменит всю палитру.
Обязательно поделитесь чем-нибудь связанным. Ура!