
CSS-переменные позволяют хранить цвета, типографику и другие параметры интерфейса в одном месте, а затем менять их набор для светлой или тёмной темы. Задайте базовые значения в корневом элементе, переопределяйте их атрибутом темы и проверьте контраст, наследование и системные настройки. Такой подход упрощает создание сайта с переключением темы и дальнейшее сопровождение стилей.
Опорные решения для системы CSS-тем
- Назначайте переменным смысловые имена: например,
--color-background, а не--gray-100. - Храните значения по умолчанию в
:root, а тематические переопределения - в отдельных селекторах. - Для ручного переключения используйте атрибут на корневом элементе, например
data-theme. - Системную тёмную тему учитывайте через
prefers-color-scheme, если пользователь не выбрал тему вручную. - Проверяйте компоненты, фокус клавиатуры и контраст текста в каждой теме.
Задайте цветовые и типографические токены через custom properties
Токены подходят для сайтов и приложений, где одна и та же роль цвета или размера повторяется в разных компонентах. Это особенно удобно при разработке интерфейса сайта с темами оформления: изменения в палитре можно централизовать, не переписывая правила отдельных кнопок и карточек.
Не стоит вводить отдельную систему переменных для нескольких уникальных стилей, если переключение темы не планируется и значения не повторяются. В таком случае достаточно обычных CSS-правил.
Начните с минимального набора:
:root {
--color-background: #ffffff;
--color-text: #202124;
--color-accent: #2457c5;
--font-body: system-ui, sans-serif;
}
body {
background: var(--color-background);
color: var(--color-text);
font-family: var(--font-body);
}
Имена описывают назначение токена, поэтому компонентам не нужно знать, какой именно оттенок сейчас используется.
Разместите базовую палитру в корневой области документа
Для начала понадобятся доступ к таблице стилей проекта и возможность проверить страницу в браузере. Изменения удобно вносить в основной CSS-файл или модуль токенов, если архитектура проекта уже разделяет стили.
- Проверьте, какой элемент является корневым: обычно это
html, выбранный через:root. - Определите повторяющиеся роли: фон страницы, поверхность карточек, основной и приглушённый текст, границы, акцент.
- Назначьте каждой роли custom property и используйте
var()в правилах компонентов. - Убедитесь, что переменные объявлены раньше правил, которые от них зависят, либо доступны через каскад.
Базовые значения задают безопасное состояние страницы, если атрибут темы ещё не установлен или скрипт переключения не сработал.
Переключайте темы атрибутом и переопределением переменных
-
Объявите значения по умолчанию.
Разместите токены в
:root. Эти значения будут использоваться, пока другая тема не переопределит их. -
Опишите альтернативную палитру.
Добавьте селектор для атрибута на корневом элементе. В нём меняйте значения токенов, а не стили каждого компонента отдельно.
:root { color-scheme: light; --color-background: #ffffff; --color-surface: #f3f5f8; --color-text: #202124; --color-accent: #2457c5; } :root[data-theme="dark"] { color-scheme: dark; --color-background: #17191d; --color-surface: #242830; --color-text: #f1f3f5; --color-accent: #9bb8ff; } -
Примените токены в интерфейсе.
Используйте переменные в стилях страницы и компонентов. Укажите резервное значение в
var(), если без него компонент должен сохранять читаемость..card { background: var(--color-surface, #f3f5f8); color: var(--color-text, #202124); } -
Свяжите переключатель темы с атрибутом.
Кнопка или иной элемент управления может менять значение
data-themeнаhtml. Сохраняйте выбор пользователя только в рамках существующей логики проекта; не полагайтесь на скрипт как на единственный способ задать читаемую тему. -
Проверьте состояние без JavaScript.
Откройте страницу без применения скрипта или временно отключите его. Базовые CSS-значения должны оставаться пригодными для чтения.
Быстрый режим
- Объявите смысловые переменные в
:root. - Переопределите нужные токены в
:root[data-theme="dark"]. - Используйте переменные в стилях компонентов через
var(). - Проверьте обе темы, состояния фокуса и отображение без скрипта.
Если планируется разработка сайта с тёмной темой, сначала согласуйте набор ролей и правила переключения, а затем подключайте палитру к компонентам. Это помогает оценить объём до начала реализации; формулировка "веб-разработка заказать" сама по себе не заменяет технического описания темы.
Согласуйте тёмную тему с системными настройками браузера
Медиавыражение prefers-color-scheme позволяет учитывать системное предпочтение. Если пользователь может выбрать тему вручную, его явный выбор должен иметь приоритет над автоматическим режимом.
- Проверьте страницу при светлой и тёмной системной настройке.
- Убедитесь, что системный режим применяется только тогда, когда пользователь не задал тему явно.
- Проверьте, что атрибут ручного выбора переопределяет автоматическую тему.
- Проверьте текст, ссылки, границы, тени и поверхности карточек.
- Проверьте видимый фокус при навигации клавиатурой в обеих темах.
- Убедитесь, что нативные элементы управления согласованы с темой; для этого может использоваться
color-scheme. - Проверьте страницу при отключённом или не сработавшем скрипте переключения.
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
color-scheme: dark;
--color-background: #17191d;
--color-text: #f1f3f5;
}
}
В этом примере системное предпочтение применяется только при отсутствии атрибута. Если проект задаёт атрибут и для светлой темы, настройте селекторы так, чтобы ручной выбор однозначно имел приоритет.
Передавайте токены компонентам через каскад и наследование
Переменные, объявленные на корневом элементе, доступны вложенным компонентам через каскад. Частые ошибки при интеграции:
- Использовать названия, завязанные на конкретный оттенок, вместо роли цвета.
- Переопределять палитру в каждом компоненте и тем самым терять единый источник значений.
- Объявлять тему на контейнере, который не содержит все нужные компоненты.
- Задавать цвет текста на одном элементе, а фон - на другом, не проверяя итоговую комбинацию.
- Ожидать наследования обычных CSS-свойств у custom properties: пользовательские свойства наследуются, но не все свойства оформления ведут себя так же.
- Создавать глобальные переменные с одинаковыми именами в несвязанных частях приложения.
- Забывать о состояниях наведения, отключённого элемента и фокуса при смене темы.
Для изолированного виджета допустимо переопределить токен на его контейнере. В этом случае локальная тема действует на вложенные элементы, не затрагивая остальную страницу.
Проверьте контрастность, области действия и резервные значения
Выберите способ управления темой по устройству проекта и ожидаемому поведению:
- Только CSS и системная настройка. Подходит, если достаточно автоматически учитывать предпочтение браузера и не требуется ручной выбор.
- Атрибут темы и JavaScript. Уместен, когда пользователь переключает режим вручную или его выбор нужно сохранить.
- Локальная тема контейнера. Подходит для встроенного виджета или отдельной области интерфейса, которая должна отличаться от страницы.
- Резервные значения в
var(). Используйте, когда компонент может подключаться вне основной темы или переменная не гарантирована стилями проекта.
Перед выпуском проверьте сочетания текста и фона инструментом проверки доступности, а также вручную протестируйте интерфейс при увеличении масштаба и навигации с клавиатуры. Для оценки объёма работ по услугам CSS-разработки подготовьте перечень компонентов, состояний и тем, которые нужно поддержать.
Нюансы внедрения CSS-переменных в темах
Где лучше объявлять переменные темы?
Общие токены обычно размещают в :root, чтобы они были доступны всей странице. Локальные значения можно объявить на контейнере конкретного виджета.
Нужно ли использовать JavaScript для смены темы?
Для автоматического учёта системного предпочтения достаточно CSS-медиавыражения. JavaScript нужен для ручного переключения и, при необходимости, сохранения выбора.
Как обеспечить приоритет ручного выбора над системной темой?
Задайте явные селекторы атрибута темы, которые переопределяют автоматические значения из медиавыражения. Проверьте отдельно отсутствие атрибута и оба возможных ручных состояния.
Зачем задавать резервное значение в var()?
Оно применяется, если указанная переменная не определена или имеет недопустимое значение для свойства. Резерв не заменяет корректную организацию токенов, но помогает компонентам сохранять базовое оформление.
Нужно ли менять типографические токены вместе с цветами?
Только если темы действительно различаются шрифтовыми параметрами. Общие типографические значения можно оставить в базовом наборе и переопределять лишь те, для которых есть конкретная причина.
Как проверить, что тема доступна для пользователей?
Проверьте контраст текста и фона, видимость фокуса клавиатуры, состояния интерактивных элементов и читаемость обеих тем. Одной визуальной проверки на обычном масштабе недостаточно.
Автор: Виктор Егоров