Перейти к содержанию

Пользовательские свойства CSS

Вынесем повторяющиеся значения в пользовательские свойства CSS и разберём их наследование на каталоге.

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

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

Имена для ролей

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

.layout-lab {
  --lab-bg: #1f202a;
  --lab-surface: #252631;
  --lab-ink: #e4e4e4;
  --lab-muted: #b7b9c9;
  --lab-link: #46d96f;
  --lab-accent: #6c43af;
  --lab-line: #3b3c4c;
  --lab-gap: 1rem;
  background: var(--lab-bg);
  color: var(--lab-ink);
}
.layout-lab a { color: var(--lab-link); }
.layout-lab .course-card {
  background: var(--lab-surface);
  border-color: var(--lab-line);
}
.layout-lab .course-card--featured {
  border-color: var(--lab-accent);
}
.layout-lab .course-count { color: var(--lab-muted); }
.layout-lab .course-list { gap: var(--lab-gap); }

Имена начинаются с двух дефисов. Мы выбрали префикс lab, чтобы показать принадлежность значения учебной странице, и смысловые роли вместо названий вроде purple. Акцент может когда-нибудь изменить оттенок, но его назначение останется прежним. Важно не выдавать такую систему имён за встроенный стандарт: браузеру достаточно корректного имени, а читаемость зависит от соглашения автора.

Ожидается прежняя палитра. Если она неожиданно изменилась, сравните значения, порядок объявлений и имена. Пользовательское свойство само по себе не окрашивает страницу. Эффект возникает там, где другое свойство использует его через var(). Можно объявить десять новых имён и не увидеть изменений, если ни одно объявление на них не ссылается.

Значение доступно в дереве

Обычные пользовательские свойства с двойным дефисом наследуются. Мы задали их на body.layout-lab, поэтому вложенные карточки могут использовать эти имена. Это удобнее глобального объявления на :root для автономного примера, поскольку значения относятся к одной странице. Механизм использования и наследования описан в MDN.

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

.layout-lab .course-card--featured {
  --lab-surface: #2d2e3b;
}

Теперь её фон должен измениться, потому что background этой карточки использует локально доступное --lab-surface. Остальные записи продолжают получать значение от страницы. Мы не создали новый селектор для всех вложенных частей: изменили данные, на которые уже ссылается компонент. После опыта уберите объявление, чтобы основной путь серии сохранял исходную палитру.

Не каждое свойство, использующее переменную, автоматически становится наследуемым. Например, фон карточки вычисляется по доступной переменной, но сам background не начинает наследоваться из-за var(). Это разные механизмы. Наследование значения имени и наследование обычного свойства нужно рассматривать отдельно, иначе трудно объяснить изменения только у выбранного компонента.

Имена чувствительны к регистру. --lab-link и --Lab-link являются разными именами. Ошибка в одной букве способна оставить объявление без ожидаемого значения. Привычка копировать имя или выбирать его через редактор уменьшает такой риск, но не отменяет проверки. В отличие от текста курса, имя переменной относится к устройству CSS и не должно меняться при редактуре заголовка.

Запасное значение и недопустимые данные

У var() можно указать запасное значение:

.layout-lab .course-list {
  gap: var(--lab-gap, 1rem);
}

Если нужное пользовательское свойство отсутствует, браузер сможет использовать второй аргумент. Это не универсальная проверка типа значения. Если --lab-gap определено как слово green, подстановка есть, но для gap она недопустима. Запасной аргумент не обязан выбирать разумное расстояние вместо любого неподходящего содержимого. Нужно различать отсутствие переменной и ошибку после подстановки.

В нашей серии значения задаются автором и не приходят из внешнего ввода. Поэтому не требуется сложная регистрация типов или преобразование данных. Достаточно понятных ролей и согласованных единиц. Если позже появится интерфейс настройки темы, он создаст новую задачу: допустимые значения, область их применения и проверку. Наличие переменной само по себе эту задачу не решает.

Не используйте var() как способ подставить часть имени CSS-свойства. Она применяется к значению объявления, а не превращает таблицу стилей в произвольный текстовый шаблон. Для выбора набора правил существуют селекторы и условия. Такое ограничение помогает оставлять механизм простым: имена значений меняют данные, правила продолжают выражать отношения элементов.

Как сократить таблицу после опыта

Мы добавляли правила последовательно, чтобы читатель видел развитие. В финальном самостоятельном проекте можно объединить старые буквальные цвета и новые обращения в один набор. При этом важно сохранить порядок варианта карточки и обычной рамки. Механическое удаление последних «повторяющихся» правил способно убрать именно те объявления, которые связывают компоненты с переменными.

Для ручной проверки поменяйте только --lab-gap с одного на полтора rem. Ожидается увеличение промежутков сетки, а внутренние поля карточек останутся прежними: они пока не используют это имя. Затем поменяйте --lab-link и сравните все ссылки страницы. Результат показывает реальную область настройки, а не обещание, что одна переменная изменяет любое расстояние или любой зелёный пиксель.

В панелях браузера можно посмотреть выбранные пользовательские значения и итог обычного свойства. Не нужно угадывать цепочку по имени: ищите место объявления и конкретную подстановку. Подробные принципы системы компонентов раскрыты в серии о дизайне. Здесь мы получили минимальную систему общих значений без изменения данных.

Значения переменных могут обращаться к другим переменным, поэтому иногда полезно отделить базовый цвет от роли компонента. Но длинная цепочка имён способна сделать поиск причины труднее. Начинайте с минимального числа уровней, которое отражает реальные решения. Если два имени всегда изменяются вместе и не выражают разных ролей, дополнительная связь может лишь усложнить исходник.

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

Пользовательские свойства существуют в браузерной модели CSS и не требуют предварительной подстановки сборщиком. Это отличает их от переменных некоторых препроцессоров, которые исчезают после генерации файла. Локальное значение на карточке может влиять на вычисление в её потомках во время отображения. Поэтому перенос переменной из одной области в другую меняет доступность значения, даже если текст объявления остался прежним. Для нашего автономного проекта такое поведение удобно: весь пример хранится в обычных файлах и открывается без отдельного шага подготовки.

Следующий урок добавит состояния ссылок, полей и кнопки. Общая палитра уже имеет имена, поэтому фон элементов управления и цвет акцента смогут использовать те же роли, сохраняя отдельные правила для фокуса, наведения и нажатия.

Оглавление курса