Тёмная тема без боли
Слои поверхностей вместо чистого чёрного, контраст текста, отдельные цвета акцента и статусов и токены, без которых тёмную тему не поддержать.
Тёмную тему часто делают за вечер: фон в чёрный, текст в белый, готово. Через неделю выясняется, что карточки сливаются с фоном, тени пропали, серый текст не читается, а в половине компонентов остались светлые куски, потому что цвет там был задан прямо в коде.
Тёмная тема — это не перекрашивание, а вторая палитра с той же логикой. Сделать её правильно несложно, если начать с основы.
Не чистый чёрный
Чистый чёрный фон с чистым белым текстом даёт максимальный контраст, и это проблема: текст режет глаза, а на некоторых экранах при прокрутке появляется смазывание. Но важнее другое — на чистом чёрном негде показать глубину.
В светлой теме поднятые элементы отделяются тенью. В тёмной тень почти не видна, поэтому глубину передают светлотой: чем выше слой, тем он светлее. Обычно хватает трёх-четырёх уровней:
- фон страницы — самый тёмный, но не чёрный;
- поверхность — карточки и панели;
- поднятая поверхность — меню и всплывающие окна;
- наведение и выделение.
Разница между уровнями небольшая, но заметная. Хорошо помогает тонкая граница: светлая линия в один пиксель с низкой непрозрачностью отделяет поверхности лучше любой тени.
Текст и контраст
Белый текст на тёмном фоне лучше чуть приглушить — светло-серый вместо чистого белого. А вот вторичный текст слишком тёмным делать нельзя: то, что на белом читалось как спокойный серый, на тёмном легко проваливается ниже допустимого контраста. Проверяй контраст в каждой теме отдельно, а не переноси значения из светлой.
Тонкие начертания на тёмном фоне выглядят ещё тоньше. Если основной текст набран лёгким весом, в тёмной теме его, возможно, стоит сделать на ступень плотнее.
Акцент и статусы
Насыщенные цвета, подобранные под белый фон, на тёмном начинают светиться и слепить. Для тёмной темы акцент и статусные цвета обычно делают светлее и чуть менее насыщенными. Красный ошибки, зелёный успеха и жёлтый предупреждения подбирай отдельно и проверяй, что они различимы и между собой, и с фоном.
Следи за текстом на акцентных кнопках: если в тёмной теме акцент стал светлым, текст на нём должен стать тёмным. Белая иконка на белой кнопке — классика жанра.
Токены
Всё это невозможно поддерживать, если цвета разбросаны по коду. Основа тёмной темы — токены, названные по роли: фон, поверхность, текст, приглушённый текст, граница, акцент. Компоненты используют только их, а темы переопределяют значения.
:root {
--bg: #ffffff;
--surface: #f5f5f6;
--text: #16161a;
--text-muted: #63636b;
--border: rgb(0 0 0 / 0.08);
}
[data-theme="dark"] {
--bg: #0f0f11;
--surface: #17171a;
--text: #e8e8ea;
--text-muted: #9a9aa2;
--border: rgb(255 255 255 / 0.08);
}
Тогда новый экран получает тёмную тему автоматически, а поиск по коду захардкоженных цветов показывает, что ещё осталось перевести.
Картинки, графики и мелочи
Логотипы и иллюстрации на прозрачном фоне в тёмной теме могут пропасть: тёмный логотип на тёмном фоне не виден. Им нужны отдельные варианты. Изображения с белым фоном смотрятся как заплатки — фон стоит вырезать.
Графикам нужны свои цвета сетки и подписей. Полям ввода, полосам прокрутки и системным элементам — правильное свойство color-scheme, иначе браузер нарисует их светлыми посреди тёмной страницы.
Выбор темы
По умолчанию следуй настройке системы и дай переключатель на три положения: светлая, тёмная, как в системе. Запоминай выбор и применяй его до отрисовки страницы, иначе при каждой загрузке экран будет мигать белым.
SUBXCAT переводит интерфейсы на токены и доводит обе темы до состояния, когда их не приходится чинить на каждом новом экране.