Уроки

Соглашения об именовании цветов в CSS и дизайн-системах

7 мин чтения

Именование цветов — обманчиво простая проблема в дизайн-системах. В небольшом масштабе это почти не имеет значения: горсть hex-кодов, разбросанных по таблице стилей, управляема. В командном масштабе, когда несколько разработчиков, дизайнеров и автоматизированных инструментов ссылаются на одну палитру, соглашения об именовании становятся несущей инфраструктурой. Плохая схема именования порождает несогласованность, расхождение между дизайн-файлами и кодом, и дорогостоящий рефакторинг. Это руководство охватывает ландшафт подходов к именованию цветов, их компромиссы и выбор правильной стратегии для вашего проекта.

CSS-именованные цвета: 148 стандартных имён

CSS включает 148 именованных цветов, которые понимает каждый браузер без hex-кода. Эти имена варьируются от очевидных стандартов вроде red, green и blue через исторические курьёзы, как rebeccapurple (добавлен в честь веб-разработчика, умершего в 2014 году), и полный набор X11, изначально используемый в Unix-графических средах.

Несколько иллюстративных примеров:

CSS-имя Hex Примечания
rebeccapurple #663399 Добавлен в CSS 4, назван в честь Ребекки Мейер
cornflowerblue #6495ED Происхождение из X11, часто используется в дефолтных UI
darkslategray #2F4F4F Принимаются оба написания: gray и grey
mediumaquamarine #66CDAA Длинные составные имена из эпохи X11
papayawhip #FFEFD5 Добавлен в CSS 1 из списка X11
aliceblue #F0F8FF Назван в честь Элис Рузвельт Лонгворт

Эти имена полезны в документации, прототипировании и небольших утилитарных стилях, где читаемость важнее точности. Однако они имеют существенные ограничения для работы с дизайн-системами:

  • Имена передают оттенок, но не уровень светлоты или насыщенности — lightblue (#ADD8E6) и skyblue (#87CEEB) — различные hex-значения без систематической взаимосвязи.
  • Они не образуют шкалу — нет предсказуемого паттерна для перехода от blue к немного более тёмному синему.
  • Имена, основанные на внешнем виде (navy, teal, coral), несут культурные ассоциации, которые могут конфликтовать со смыслом, задуманным брендом.
  • Полный список из 148 имён нельзя запомнить, что делает вероятным использование разных имён разными членами команды для цветов, которые они считают одинаковыми.

Для всего, что выходит за рамки простого прототипирования, замените CSS-именованные цвета одним из структурированных подходов к именованию ниже.

Семантическое именование с CSS-кастомными свойствами

Семантическое именование привязывает цветовые переменные к их назначению в UI, а не к визуальному виду. Вместо --blue-500 определяется --color-primary. Вместо --gray-200--color-background-subtle.

Паттерн семантического слоя

Хорошо структурированная семантическая палитра имеет два слоя. Примитивный слой отображает описательные имена на сырые hex-значения:

/* Примитивная палитра — никогда не используется напрямую в компонентах */
:root {
  --blue-50:   #EFF6FF;
  --blue-100:  #DBEAFE;
  --blue-500:  #3B82F6;
  --blue-600:  #2563EB;
  --blue-900:  #1E3A8A;

  --gray-50:   #F9FAFB;
  --gray-100:  #F3F4F6;
  --gray-200:  #E5E7EB;
  --gray-700:  #374151;
  --gray-900:  #111827;
}

Семантический слой ссылается на примитивные значения и присваивает имена, основанные на назначении:

/* Семантическая палитра — используется во всех стилях компонентов */
:root {
  --color-primary:           var(--blue-500);
  --color-primary-hover:     var(--blue-600);
  --color-primary-subtle:    var(--blue-50);

  --color-background:        var(--gray-50);
  --color-surface:           #FFFFFF;
  --color-text:              var(--gray-900);
  --color-text-muted:        var(--gray-700);
  --color-border:            var(--gray-200);
}

Преимущество двухслойного подхода — гибкость тёмной темы. Для смены тем переопределяется только семантический слой — примитивы остаются неизменными:

[data-theme="dark"] {
  --color-primary:       var(--blue-400); /* более светлый оттенок для тёмного фона */
  --color-background:    var(--gray-900);
  --color-surface:       var(--gray-800);
  --color-text:          var(--gray-50);
  --color-text-muted:    var(--gray-400);
  --color-border:        var(--gray-700);
}

Таксономии семантического именования

Разные организации выбирают разные структуры семантических имён. Наиболее распространённый паттерн использует структуру роль + вариант:

/* Роль: background, surface, border, text, icon, focus */
--color-background-base
--color-background-subtle
--color-background-inverse

/* Вариант: default, subtle, strong, inverse */
--color-text-default
--color-text-subtle
--color-text-strong
--color-text-on-primary

Другая популярная таксономия разделяет интерактивное состояние:

--color-interactive-default
--color-interactive-hover
--color-interactive-active
--color-interactive-disabled
--color-interactive-focus-ring

Точная таксономия важна меньше, чем внутренняя согласованность. Выберите одну и соблюдайте её.

Преимущества семантического именования

  • Тёмная тема реализуется легко — переопределите семантические переменные, все компоненты обновятся автоматически
  • Читаемость с первого взглядаvar(--color-text-muted) мгновенно передаёт намерение; #6B7280 — нет
  • Согласованность дизайнера и разработчика — Figma также поддерживает именование цветов на основе токенов; одни и те же имена могут появляться в обоих инструментах (стандарт Design Tokens)
  • Безопасность рефакторинга — чтобы изменить основной синий, обновите одну переменную; ничего больше не меняется

Недостатки

  • Требует дисциплины для поддержания — без принуждения разработчики возвращаются к жёстко заданным hex-кодам
  • Именование по природе субъективно — --color-surface-raised против --color-bg-elevated провоцирует споры
  • Слишком детализированные семантические имена становятся столь же неуправляемыми, как и отсутствие системы вовсе

Шкальное именование: соглашение blue-500

Шкальное именование (также называемое числовым именованием или именованием в стиле Tailwind) полностью игнорирует назначение и фокусируется на позиции в шкале яркости. Каждое семейство цветов получает имя и числовой диапазон, обычно от 50 до 950 с шагом 50 или 100. Большие числа — темнее.

/* Шкала синего */
--blue-50:   #EFF6FF;  /* Почти белый, с синим оттенком */
--blue-100:  #DBEAFE;
--blue-200:  #BFDBFE;
--blue-300:  #93C5FD;
--blue-400:  #60A5FA;
--blue-500:  #3B82F6;  /* Средняя точка — максимальная насыщенность */
--blue-600:  #2563EB;
--blue-700:  #1D4ED8;
--blue-800:  #1E40AF;
--blue-900:  #1E3A8A;
--blue-950:  #172554;  /* Почти чёрный, с синим оттенком */

Генератор оттенков автоматически генерирует шкалы такого типа: введите любое базовое hex-значение, и он вычисляет полный диапазон 50–950, используя перцептивно равномерные шаги, давая готовую шкалу для пользовательских цветов бренда.

Как работает шкальное соглашение

Tailwind CSS популяризировал это соглашение, и его палитра — де-факто эталонная реализация. Логика:

  • 50: Едва тонированный белый — подходит для фонов при наведении, тонких индикаторов
  • 100–200: Светлые оттенки — подходят для фонов в светлой теме, заливок бейджей
  • 300–400: Более светлые средние тона — работают для границ, иконок на белом
  • 500: «Чистый» оттенок — максимальная насыщенность при данном тоне, цвет идентичности
  • 600–700: Темнее — основные интерактивные состояния (наведение, нажатые кнопки)
  • 800–900: Глубокий — текст на светлых фонах, тёмный UI-хром
  • 950: Почти чёрный — высококонтрастный текст, базовые поверхности тёмной темы

Когда шкальное именование хорошо работает

Шкальное именование превосходит в utility-first CSS-фреймворках и в дизайн-системах, где примитивные цвета определяются отдельно от их применения. Оно явное — всегда известно точное соотношение яркости между blue-300 и blue-700. Добавление нового оттенка не требует суждений об именовании.

Главное ограничение в том, что шкальные имена не передают назначение. Обзор компонента, использующего var(--blue-600), ничего не говорит о том, это цвет текста, фона, иконки или кольца фокуса. По этой причине шкальные имена лучше всего работают как примитивный слой под семантическими именами, а не как финальный API для потребителей.

Имена цветов бренда

Фирменные цвета представляют особую задачу именования, поскольку часто требуют имён, узнаваемых внутри компании, но не отображающихся чисто на общие шкалы. Компания с отличительным бирюзовым в качестве основного цвета может иметь:

/* Метод 1: Название бренда напрямую */
:root {
  --color-brand-teal:      #00897B;
  --color-brand-teal-dark: #00695C;
  --color-brand-gold:      #F59E0B;
}
/* Метод 2: Название бренда + шкала */
:root {
  --ocean-400: #26C6DA;
  --ocean-500: #00BCD4;
  --ocean-600: #00ACC1;
  --ocean-700: #0097A7;
}
/* Метод 3: Гибрид бренда и роли */
:root {
  --color-brand-primary:   #00897B;
  --color-brand-secondary: #F59E0B;
  --color-brand-neutral:   #607D8B;
}

Крупные дизайн-системы выбирают по-разному. Google Material Design использует md-sys-color-primary (на основе роли). Рекомендации Apple по человеческому интерфейсу ссылаются на семантические имена вроде «Label» и «System Blue». Система IBM Carbon использует имена ролей: $brand-01, $brand-02. Shopify Polaris использует --p-color-bg-interactive.

Опасность привязки к цветовому имени

Одна из распространённых ошибок — называть цвет по его визуальному виду: --color-teal, --color-orange. Это работает до тех пор, пока бренд не обновляется и тот бирюзовый не становится сине-зелёным. Теперь каждая ссылка на --color-teal в кодовой базе семантически неверна, даже если базовый hex изменился.

Самый безопасный подход — называть фирменные цвета по их роли (--color-primary) или по абстрактному идентификатору бренда (--color-horizon, --color-midnight), а не по визуальным качествам. Имена ролей переживают ребрендинг; визуальные имена — нет.

Лучшие практики для команд

Устанавливайте стандарт токенов заблаговременно

Определите соглашение об именовании в общем документе до написания любого CSS. Ответьте на эти вопросы:

  1. Используем ли мы семантические имена, шкальные имена или оба слоя?
  2. Какой у нас разделитель: kebab-case (--color-text-primary) или точечная нотация (color.text.primary)?
  3. Как мы обрабатываем состояния (hover, active, disabled, focus)?
  4. Как мы обрабатываем темы (тёмная тема, режим высокого контраста, брендовые темы)?

Письменный стандарт, соблюдаемый с помощью линтера (у Stylelint есть плагин для именования кастомных свойств), предотвращает постепенное расхождение, превращающее чистую систему в хаос.

Синхронизируйте дизайн-токены между Figma и кодом

Рабочая группа W3C по дизайн-токенам разработала спецификацию формата токенов на основе JSON. Инструменты вроде Style Dictionary, Theo и Tokens Studio для Figma позволяют определить цвета один раз в файле — источнике истины — и одновременно генерировать CSS-кастомные свойства, конфигурацию Tailwind, константы iOS Swift и XML для Android.

Минимальный файл токенов:

{
  "color": {
    "primary": { "$value": "#3B82F6", "$type": "color" },
    "primary-hover": { "$value": "#2563EB", "$type": "color" },
    "background": { "$value": "#F9FAFB", "$type": "color" },
    "text": { "$value": "#111827", "$type": "color" }
  }
}

Style Dictionary преобразует это в CSS-кастомные свойства, конфигурацию Tailwind или любой другой нужный формат.

Ограничивайте палитру

Одна из наиболее распространённых неудач системы именования — разрастание палитры: система начинается с 6 цветов и заканчивается 60, многие из которых являются незначительными вариациями, отличающимися одним-двумя hex-символами. Установите максимальный размер палитры. Любой новый цвет должен либо заменить существующий, либо обосновать новую семантическую роль.

Используйте Генератор оттенков для генерации полного диапазона тонов и оттенков от одного базового цвета. Это обеспечивает математическую согласованность каждой шкалы и предотвращает накопление вручную подобранных почти-дубликатов.

Документируйте каждое имя

Каждая цветовая переменная в вашей системе должна иметь однофразовое описание предполагаемого использования. Эта документация размещается рядом с определениями переменных или в специальном каталоге токенов. Будущим членам команды — и вам в будущем — нужно будет ответить на вопрос «какая переменная для границы вторичной кнопки?» без чтения всего CSS компонентов.

/* --color-border-interactive
 * Границы полей форм, чекбоксов, радиокнопок и меню выбора
 * в их дефолтном (без наведения, без фокуса) состоянии.
 * Контрастность: должна проходить 3:1 относительно --color-surface (порог WCAG для нетекстовых элементов)
 */
--color-border-interactive: #D1D5DB;

Используйте линтер для соблюдения соглашения

Stylelint с плагином stylelint-declaration-block-no-ignored-properties может перехватывать сырые hex-значения, используемые вне примитивного слоя:

{
  "rules": {
    "color-named": "never",
    "color-no-hex": [true, {
      "severity": "warning",
      "message": "Используйте CSS-кастомное свойство из палитры дизайн-токенов вместо сырого hex-значения."
    }]
  }
}

Это правило будет отмечать любой сырой цветовой литерал вроде color: #3B82F6, который должен быть color: var(--color-primary).

Ключевые выводы

  • 148 именованных цветов CSS хороши для документации и быстрого прототипирования, но их несистематичный характер делает их непригодными для дизайн-систем с несколькими членами команды.
  • Семантическое именование (--color-text-primary, --color-background-subtle) привязывает имена переменных к их назначению в UI, упрощая реализацию тёмной темы и рефакторинг.
  • Шкальное именование (blue-500, gray-200) определяет иерархию яркости внутри каждого семейства цветов — Генератор оттенков автоматизирует генерацию шкалы из любого базового hex-значения.
  • Наиболее надёжные системы используют оба слоя: примитивный шкальный слой как сырые значения и семантический слой, ссылающийся на примитивные переменные и предоставляющий компонентам имена на основе назначения.
  • Называйте фирменные цвета по роли (--color-primary) или по абстрактным идентификаторам бренда, а не по визуальным качествам (--color-teal), чтобы пережить ребрендинг.
  • Соблюдайте соглашение об именовании с помощью линтера, синхронизируйте токены между дизайн-инструментами и кодом, используя стандарт токенов, и документируйте предполагаемое использование каждой переменной.

Похожие цвета

Похожие бренды

Похожие инструменты