Когда заказчик говорит «хочу тёмную тему», первое, что приходит в голову неопытному дизайнеру — взять существующий интерфейс и инвертировать цвета. Белый фон становится чёрным, тёмный текст — светлым. Готово? Нет. Именно такой подход даёт большинство плохих тёмных тем: взгляд устаёт, контраст ломается, иконки выглядят странно, а тени и вовсе перестают работать как задумано.

Тёмная тема — это отдельная дизайн-система, а не производная от светлой.

Почему инверсия не работает

Человеческий глаз воспринимает тёмный и светлый интерфейс принципиально по-разному. На светлом фоне зрачок сужается, на тёмном — расширяется. Это меняет восприятие контраста, насыщенности и даже читаемости текста.

Проблема первая: насыщенные цвета на чёрном фоне «горят» слишком ярко. Если в светлой теме у вас кнопка цвета #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-система.

Главный принцип: тёмная тема — это не про «сделать тёмно». Это про то, чтобы пользователь в любых условиях мог комфортно работать с интерфейсом.