Статьи

Использование Sass для создания цветовых палитр

На днях разработчик пользовательского интерфейса Александр Броудин спросил меня, как я буду использовать 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-palettecolors Например:

 $green-palette: create-palette(lightgreen);
// Returns: #f4f1f3 #d5d5d5 #c2cec0 lightgreen #79b079 #4f864f #497c49

Довольно аккуратно, а?

Делать вещи лучше

Список цветов — не самый лучший способ справиться с цветами. Что вы собираетесь использовать? nth($green-palette, 3) Не очень практично. Что если мы превратили этот список в карту с явными ключами, такими как: lightestlighterlightbasedarkdarkerdarkest Тогда вы можете сказать 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, внизу. Изменение любого из шести цветов изменит всю палитру.

Обязательно поделитесь чем-нибудь связанным. Ура!