Когда заказчик говорит «хочу тёмную тему», первое, что приходит в голову неопытному дизайнеру — взять существующий интерфейс и инвертировать цвета. Белый фон становится чёрным, тёмный текст — светлым. Готово? Нет. Именно такой подход даёт большинство плохих тёмных тем: взгляд устаёт, контраст ломается, иконки выглядят странно, а тени и вовсе перестают работать как задумано.
Тёмная тема — это отдельная дизайн-система, а не производная от светлой.
Почему инверсия не работает
Человеческий глаз воспринимает тёмный и светлый интерфейс принципиально по-разному. На светлом фоне зрачок сужается, на тёмном — расширяется. Это меняет восприятие контраста, насыщенности и даже читаемости текста.
Проблема первая: насыщенные цвета на чёрном фоне «горят» слишком ярко. Если в светлой теме у вас кнопка цвета #0052CC (насыщенный синий), то на тёмном фоне она будет буквально резать глаз. Зрачок расширен, светлые объекты воспринимаются агрессивнее. В Apple Human Interface Guidelines прямо написано: в тёмном режиме используйте менее насыщенные варианты акцентных цветов.
Проблема вторая: чисто белый текст (#FFFFFF) на чёрном (#000000) — это слишком высокий контраст. Звучит парадоксально, но такой контраст вызывает эффект «ирлиненовых ореолов» (irradiation illusion): светлые буквы как будто размываются на тёмном фоне. Читать длинные тексты становится некомфортно. Именно поэтому большинство нормальных тёмных тем используют не #000000, а что-то вроде #121212 или #1E1E1E для фона, и не #FFFFFF, а #E0E0E0 или #F5F5F5 для основного текста.
Проблема третья: тени. В светлой теме тень — это инструмент глубины. Карточка с box-shadow выглядит приподнятой над фоном. Если просто инвертировать цвета, тень станет светлой на тёмном фоне — и превратится в свечение. Это не всегда плохо, но требует отдельного осмысления.
Как строить палитру для тёмной темы
Правильный подход — не брать светлую палитру и менять значения, а выстраивать новую с нуля, опираясь на те же смысловые роли.
Фоновые слои. В Material Design 3 (Google) используется понятие elevation — каждый слой интерфейса имеет свой уровень глубины. В светлой теме это достигается тенями. В тёмной — тонкими оттенками фона: чем выше элемент «висит», тем чуть светлее его фон. Разница между слоями небольшая: 4–8% по яркости. Например:
- Основной фон: #121212
- Карточки первого уровня: #1E1E1E
- Карточки второго уровня: #252525
- Поверхности поверх: #2C2C2C
Это даёт ощущение глубины без теней и без инверсии.
Акцентные цвета. Берём базовый акцент из светлой темы и сдвигаем его в сторону меньшей насыщенности и чуть большей яркости. Тот же синий #0052CC в тёмной теме может стать #4D9FFF — светлее, но спокойнее. Проверяем контраст по WCAG: для основного текста нужно минимум 4.5:1, для крупных заголовков — 3:1.
Цвета состояний. Зелёный «успех», красный «ошибка», жёлтый «предупреждение» — всё это тоже нужно пересматривать. Чистый красный #FF0000 на тёмном фоне выглядит агрессивно. Используйте приглушённые варианты: #CF6679 вместо #B00020, #81C995 вместо #34A853.
Типографика в тёмной теме
Светлый текст на тёмном фоне требует другого подхода к весу шрифта. Тонкие засечки и лёгкие начертания, которые прекрасно смотрятся на белом, на тёмном фоне «растворяются» или теряют чёткость.
Практическое правило: в тёмной теме используйте шрифтовые начертания на один-два шага жирнее, чем в светлой. Если в светлой теме у вас body text с font-weight: 400, в тёмной лучше поставить 400–450 (если шрифт поддерживает variable font) или перейти на 500.
Размер шрифта трогать не нужно — он остаётся тем же. Но межстрочный интервал можно чуть увеличить: это компенсирует эффект размытости при расширенном зрачке.
Отдельная история — ссылки. В светлой теме синяя ссылка на белом фоне — классика. В тёмной теме насыщенный синий на тёмно-сером фоне может иметь недостаточный контраст. Всегда проверяйте через инструменты: Colour Contrast Analyser, встроенный инспектор Chrome DevTools или Figma-плагин Stark.
Иконки и иллюстрации
Здесь часто возникает неожиданная проблема. Монохромные иконки работают нормально — просто меняем цвет с тёмного на светлый. Но с цветными иллюстрациями, скриншотами и фотографиями всё сложнее.
Фотографии на тёмном фоне смотрятся хуже, если у них белый или светлый фон. Стандартное решение — добавить тёмное обрамление или лёгкое затемнение через CSS-фильтр. Но лучше изначально проектировать систему так, чтобы изображения не имели белого фона там, где это мешает.
SVG-иконки с hardcoded цветами — отдельная боль. Если иконка нарисована с fill="#000000", она будет чёрной в обеих темах. Правило: все иконки должны использовать currentColor или CSS-переменные, чтобы нормально адаптироваться.
Логотипы — отдельный разговор. Хороший логотип существует в двух вариантах: для светлого и тёмного фона. Если логотип один и он тёмный — в тёмной теме его просто не будет видно. Это частая проблема при разработке, которую замечают уже после запуска.
Тени и глубина
В светлой теме тень создаётся тёмным цветом с прозрачностью. В тёмной теме тот же приём работает слабо: тёмная тень на тёмном фоне почти незаметна.
Есть два подхода:
Первый — elevation через цвет фона, как описано выше. Карточки просто немного светлее фона, и это создаёт ощущение слоёв. Так делает Material Design.
Второй — свечение вместо тени. Вместо тёмной тени снизу — лёгкое светлое свечение по краям элемента. Выглядит необычно, но при аккуратном применении работает хорошо. Многие UI-библиотеки для тёмных интерфейсов используют именно этот приём.
Важно: не пытайтесь сохранить тени из светлой темы в тёмной через инверсию. Светлая тень на тёмном фоне выглядит как свечение — и это создаёт ощущение нереалистичности.
CSS и реализация
Технически тёмную тему можно реализовать несколькими способами. Самый гибкий и правильный — CSS custom properties (переменные).
Вместо того чтобы писать:
.button { background: #0052CC; color: #FFFFFF; }
Пишем:
:root {
--color-primary: #0052CC;
--color-on-primary: #FFFFFF;
--color-surface: #FFFFFF;
--color-on-surface: #1A1A1A;
}
[data-theme="dark"] {
--color-primary: #4D9FFF;
--color-on-primary: #003380;
--color-surface: #121212;
--color-on-surface: #E0E0E0;
}
.button {
background: var(--color-primary);
color: var(--color-on-primary);
}
Тогда переключение темы — это просто смена атрибута data-theme на корневом элементе. Все компоненты адаптируются автоматически.
Для определения системной темы пользователя используйте медиа-запрос:
@media (prefers-color-scheme: dark) {
:root {
--color-primary: #4D9FFF;
/* ... */
}
}
Но всегда давайте пользователю возможность переключить тему вручную — не все с тёмным режимом в ОС хотят его везде.
Частые ошибки
Чисто чёрный фон. #000000 — плохой выбор для основного фона в тёмной теме. Слишком резкий контраст с любым контентом. Используйте тёмно-серые оттенки.
Слишком яркий акцент. Насыщенные цвета на тёмном фоне утомляют. Сделайте акценты чуть менее насыщенными и чуть светлее.
Не проверен контраст. WCAG 2.1 обязателен для обеих тем. В тёмной теме нарушения контраста встречаются чаще, особенно на placeholder-тексте, secondary-элементах и disabled-состояниях.
Одна иконка для двух тем. Даже монохромные иконки иногда нужно адаптировать: толщину stroke, размер, наличие заливки.
Забыли про скриншоты и превью. Если на сайте есть блок с примерами работ или скриншотами интерфейсов — в тёмной теме они могут смотреться неорганично. Нужно либо адаптировать обрамление, либо иметь тёмные версии.
Анимации переключения. Переход между темами без анимации выглядит резко. Достаточно добавить transition: background-color 0.2s, color 0.2s на основные элементы.
Нужна ли вообще тёмная тема
Не каждому сайту она нужна. По данным Android Authority (2023), около 82% пользователей смартфонов используют тёмную тему на устройстве. Но это не значит, что они ожидают её на каждом сайте.
Для корпоративных сайтов-визиток и лендингов тёмная тема — опционально. Для приложений, дашбордов, инструментов, которыми пользуются долго — практически обязательна.
Если ресурсов на качественную тёмную тему нет — лучше не делать её вообще, чем делать плохо. Инвертированная светлая тема хуже отсутствия тёмной темы: она создаёт иллюзию заботы о пользователе, но при этом раздражает.
В REEXY при разработке корпоративных сайтов мы всегда обсуждаем с клиентом необходимость тёмной темы на старте проекта — потому что добавить её потом, не заложив в архитектуру CSS изначально, значит переписывать значительную часть стилей.
Как тестировать
Проверяйте тёмную тему не только в браузере на мониторе с хорошей цветопередачей. Тёмные интерфейсы по-разному выглядят на:
- IPS и OLED-экранах (OLED даёт настоящий чёрный, IPS — подсвеченный тёмно-серый)
- Мониторах с разной гаммой
- Мобильных устройствах при разном уровне яркости
Инструменты: Chrome DevTools позволяет эмулировать prefers-color-scheme прямо в инспекторе. Figma поддерживает переменные для тем — можно переключать тему в дизайне одним кликом. Stark и Contrast — плагины для проверки доступности.
Попросите нескольких человек протестировать тёмную тему вечером при слабом освещении. Именно в этих условиях она используется чаще всего — и именно тогда становятся заметны все проблемы с контрастом и насыщенностью.
Что в итоге
Тёмная тема — это дизайн-решение, которое требует той же внимательности, что и светлая. Нужно пересмотреть палитру, проверить типографику, адаптировать иконки и пересобрать логику теней. Это не сложно, если заложить правильную архитектуру в начале — CSS-переменные, семантические роли цветов, elevation-система.
Главный принцип: тёмная тема — это не про «сделать тёмно». Это про то, чтобы пользователь в любых условиях мог комфортно работать с интерфейсом.