Как смешивать цвета и создавать палитры на Sass
Смешивание цветов Sass помогает получить варианты фирменного цвета без ручного подбора. Вы зададите два базовых цвета, соберете палитру и выведете ее в CSS-переменные.
Разберем color.scale(), color.adjust(), color.mix() и CSS-функции. В конце вы проверите контраст текста и фона.
- Переменные бренда в Sass
- Почему lighten и darken дают резкий результат
- Получите оттенки через color.scale
- Сравните функции цвета Sass и CSS
- Смешайте цвет с собственными тонами
- Соберите палитру и выведите CSS-переменные
- Когда выбрать color-mix и относительные цвета в CSS
- Проверьте контраст текста и фона
- Как выбрать функцию цвета для палитры
Переменные бренда в Sass
Назовите базовые цвета до расчета светлых и темных вариантов. Такое имя понятнее повторяющегося HEX-кода.
Пример использует красный $toolbox и синий $ol-blue. Запишите их в файле palette.scss через HSL:
@use "sass:color";
$toolbox: hsl(0, 50%, 40%); // #993333
$ol-blue: hsl(210, 50%, 60%); // #6699cc
button {
background-color: $toolbox;
background-image: linear-gradient(
hsl(0, 33%, 52%),
$toolbox,
hsl(0, 41%, 39%)
);
}Это SCSS. Браузер не понимает переменные с символом $. Dart Sass превращает их в обычный CSS.
Скомпилируйте файл командой sass palette.scss palette.css. Рядом появится файл palette.css. Подключите его к странице:
<link rel="stylesheet" href="palette.css">
<button type="button">Добавить в корзину</button>Кнопка получит красный фон с градиентом.
Подключайте функции цвета через модуль sass:color.
Глобальные lighten(), darken(), scale-color(), adjust-hue() и mix() объявлены устаревшими в Dart Sass. Используйте color.adjust(), color.scale() и color.mix().

Оттенок света меняет восприятие одной и той же палитры.
Почему lighten и darken дают резкий результат
Старые функции меняют светлоту на фиксированное число процентных пунктов. Значение «осветлить на 50%» легко понять неправильно.
У $toolbox светлота равна 40%. У $ol-blue она равна 60%. Прибавление 50 процентных пунктов даст красному цвету 90%.
Синий цвет упрется в предел 100% и станет белым. При затемнении действует тот же принцип.
.fixed-step {
color: color.adjust($toolbox, $lightness: 50%);
background-color: color.adjust($ol-blue, $lightness: 50%);
}


Светлота HSL задает координату цвета, но не измеряет воспринимаемую яркость.
Два цвета с одинаковой светлотой могут выглядеть по-разному. Поэтому HSL не гарантирует читаемость текста.
Получите оттенки через color.scale
color.scale() меняет канал на долю расстояния до его предела.
Положительное значение светлоты приближает цвет к белому. Отрицательное значение приближает цвет к черному. Исходная светлота влияет на результат.
.scaled {
color: color.scale($toolbox, $lightness: 50%);
background-color: color.scale($ol-blue, $lightness: -30%);
}Красный изменит светлоту с 40% до 70%. Синий при уменьшении на 30% получит 42%.




Значение 100% дает белый цвет. Значение −100% дает черный цвет.
@mixin brand-button($base) {
background-color: $base;
background-image: linear-gradient(
color.scale($base, $lightness: 50%),
$base,
color.scale($base, $lightness: -30%)
);
&:hover,
&:focus {
background-color: color.scale($base, $lightness: 10%);
background-image: linear-gradient(
color.scale($base, $lightness: 60%),
color.scale($base, $lightness: 10%),
color.scale($base, $lightness: -20%)
);
}
}
button {
@include brand-button($toolbox);
}
button.secondary {
@include brand-button($ol-blue);
}Примесь получает базовый цвет и рассчитывает градиент для состояний кнопки.
Для сдвига оттенка используйте color.adjust($ol-blue, $hue: 20deg). Функция color.scale() оттенок не сдвигает.
Сравните функции цвета Sass и CSS
Функции меняют цвет по-разному. Выбирайте их по нужному результату.
| Функция | Что делает | Пример | Когда считает цвет |
|---|---|---|---|
color.adjust() | Прибавляет фиксированное значение канала | color.adjust(hsl(210, 50%, 60%), $lightness: 20%) | При сборке Sass |
color.scale() | Проходит долю расстояния до предела канала | color.scale(hsl(210, 50%, 60%), $lightness: 50%) | При сборке Sass |
color.mix() | Смешивает два цвета в выбранном пространстве | color.mix(white, #993333, $weight: 50%, $method: rgb) | При сборке Sass |
color-mix() | Смешивает цвета в браузере | color-mix(in srgb, white 50%, #993333) | Во время работы страницы |
Смешайте цвет с собственными тонами
color.mix() рассчитывает промежуточный цвет между двумя исходными. Параметр $weight задает долю первого цвета.
$blue-light: color.mix(white, $ol-blue, $weight: 60%, $method: rgb);
$blue-dark: color.mix(black, $ol-blue, $weight: 30%, $method: rgb);Параметр $method поддерживается Dart Sass начиная с версии 1.79.0. Значение rgb задает интерполяцию в RGB.
Смешивание в RGB интерполирует цветовые каналы, не повторяя изменение светлоты HSL.
Поэтому результаты color.mix() и color.scale() различаются. Другие пространства интерполяции описаны в документации color.mix().
$light: #fff2b3;
$shadow: #34204f;
$toolbox-light: color.mix($light, $toolbox, $weight: 60%, $method: rgb);
$toolbox-dark: color.mix($shadow, $toolbox, $weight: 30%, $method: rgb);
$blue-light: color.mix($light, $ol-blue, $weight: 60%, $method: rgb);
$blue-dark: color.mix($shadow, $ol-blue, $weight: 30%, $method: rgb);
.card {
background-color: $blue-light;
border-color: $blue-dark;
}









Замените $light и $shadow, чтобы изменить настроение всей палитры. Sass пересчитает зависимые смеси при следующей сборке.
Соберите палитру и выведите CSS-переменные
Карта Sass хранит базовые цвета. Цикл @each создает свойства в :root.
@use "sass:color";
$brands: (
"toolbox": #993333,
"ol-blue": #6699cc
);
$light: white;
$shadow: black;
:root {
@each $name, $base in $brands {
--color-#{$name}: #{$base};
--color-#{$name}-light: #{color.mix($light, $base, $weight: 50%, $method: rgb)};
--color-#{$name}-dark: #{color.mix($shadow, $base, $weight: 50%, $method: rgb)};
}
}
.button {
background-color: var(--color-toolbox);
color: white;
}
.button:hover {
background-color: var(--color-toolbox-dark);
}Интерполяция #{…} вставляет значение Sass в пользовательское свойство CSS.
Запустите sass palette.scss palette.css. Компилятор создаст 6 CSS-переменных. Итоговый CSS будет выглядеть так:
:root {
--color-toolbox: #993333;
--color-toolbox-light: #cc9999;
--color-toolbox-dark: #4d1a1a;
--color-ol-blue: #6699cc;
--color-ol-blue-light: #b3cce6;
--color-ol-blue-dark: #334d66;
}
.button {
background-color: var(--color-toolbox);
color: white;
}
.button:hover {
background-color: var(--color-toolbox-dark);
}Добавьте на страницу кнопку с классом button. При наведении фон изменится на темный вариант.
Меняйте значение цвета, например #993333, в карте $brands. Затем повторите компиляцию.
Имена ключей toolbox и ol-blue оставляйте прежними. Они определяют имена CSS-переменных, которые используют стили кнопки.
Когда выбрать color-mix и относительные цвета в CSS
Sass считает цвета во время сборки, поэтому браузер получает готовые значения.
Изменение CSS-переменной без пересборки не обновит оттенки Sass. Для темы, которая меняется во время работы страницы, используйте CSS-функции.
Нативная функция color-mix() смешивает цвета в браузере. Она принимает CSS-переменную:
:root {
--brand: #6699cc;
}
.badge {
background-color: #b3cce6;
}
@supports (background-color: color-mix(in srgb, white, black)) {
.badge {
background-color: color-mix(in srgb, white 50%, var(--brand));
}
}При изменении --brand браузер пересчитает фон без запуска Sass.
Условие @supports проверяет поддержку объявления. Запасной цвет останется для браузера без этой функции.
Относительный синтаксис цвета меняет каналы исходного цвета:
.badge-relative {
background-color: #b3cce6;
}
@supports (background-color: hsl(from red h s l)) {
.badge-relative {
background-color: hsl(
from var(--brand)
h s calc(l + (100 - l) * 0.5)
);
}
}В относительном HSL канал l принимает значение от 0 до 100. Формула увеличивает светлоту на половину оставшегося расстояния.
Выбирайте Sass для дизайн-токенов и статичной палитры. Выбирайте CSS-функции для темы, которая меняется через переменные.
Проверьте контраст текста и фона
Гармоничная палитра не гарантирует читаемость.
Проверяйте обычное состояние, наведение, фокус и выбранное состояние.
Критерий 1.4.3 WCAG 2.1 задает пороги для уровня AA. Обычному тексту нужен контраст 4,5:1.
Для крупного текста нужен контраст 3:1. Уровень AAA требует 7:1 для обычного текста и 4,5:1 для крупного.
Критерий нетекстового контраста задает порог 3:1 для значимых границ и состояний элементов.
Для непрозрачных цветов рассчитайте контраст в консоли браузера. Функция принимает шестизначные HEX-коды:
function contrast(hex1, hex2) {
function luminance(hex) {
const channels = hex.replace(/^#/, "").match(/.{2}/g).map(part => {
const value = parseInt(part, 16) / 255;
return value <= 0.04045
? value / 12.92
: ((value + 0.055) / 1.055) ** 2.4;
});
return channels[0] * 0.2126
+ channels[1] * 0.7152
+ channels[2] * 0.0722;
}
const a = luminance(hex1);
const b = luminance(hex2);
return (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);
}
console.log(contrast("#ffffff", "#993333"));Для пары #000000 и #ffffff функция вернет 21.
Если коэффициент ниже порога, измените цвет текста или фона. На градиенте проверьте участок под буквами с самым слабым результатом.
Функция не учитывает прозрачность, изображения и наложенные слои. Сначала определите итоговый отображаемый цвет.
Как выбрать функцию цвета для палитры
color.adjust()– используйте фиксированное изменение канала или сдвиг оттенка.color.scale()– получайте светлые и темные варианты с учетом исходной светлоты.color.mix()– добавляйте общий цвет света или тени к нескольким базовым цветам.- Карта Sass и
@each– экспортируйте дизайн-токены как свойства--color-*. color-mix()и относительные цвета CSS – меняйте тему без пересборки Sass.
Совет от нашей редакции: сначала проверьте одну кнопку с текстом. Сравните обычное состояние, наведение и клавиатурный фокус. После этого применяйте палитру ко всему интерфейсу.
Популярное за неделю
- Как создать сайт самому в 2026: 4 способа + пошаговая инструкция 34 мин чтения
- Лучшие конструкторы для создания сайтов — плюсы, минусы и сравнения 22 мин чтения
- overflow hidden что это и почему обрезка не работает 6 мин чтения
- 50 примеров CSS3‑кнопок с эффектами для сайта 5 мин чтения
- 17 эффектных CSS‑анимаций с готовыми примерами 3 мин чтения
- 19 CSS‑спиннеров и прелоадеров для загрузки 5 мин чтения
Комментарии