Добавление тёмной темы на сайт

Тёмная тема — это альтернативная цветовая схема, которая заменяет светлый фон на тёмный и делает интерфейс комфортнее в условиях низкой освещённости. Кроме эстетики, она снижает нагрузку на глаза и может экономить заряд на OLED‑экранах.
В этой статье вы найдёте готовые блоки кода, улучшенные рекомендации по UX и проверочную матрицу для разработки и тестирования. Всё представлено простыми предложениями и пошагово.
Что такое тёмная тема и зачем она нужна
Тёмная тема — это набор стилей, ориентированных на тёмный фон и светлый текст. Она особенно полезна:
- в вечернее и ночное время;
- для пользователей с повышенной чувствительностью к яркому свету;
- на устройствах с OLED, где чёрные пиксели выключаются и экономят энергию.
Ключевой принцип: обеспечить достаточный контраст, предсказуемость интерфейса и возможность вернуть прежнюю визуализацию одним кликом.
Подготовка проекта
Убедитесь, что у вас структурированы HTML, CSS и JavaScript файлы. Ниже — минимальный пример разметки с контейнером переключателя темы.
HTML
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Odit deserunt sit neque in labore quis quisquam expedita minus
perferendis.
Важно: оставляйте понятные id и class (например, theme__switcher), чтобы код и стили были читаемы и поддерживаемы.
CSS: базовая светлая тема
Этот CSS выступает в роли «по умолчанию» — светлая тема. Позже мы добавим классы для тёмной и светлой темы.
@import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@400;700&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html { font-size: 62.5%; }
body { font-family: "Quicksand", sans-serif; }
.navbar {
display: flex;
padding: 2rem;
font-size: 1.6rem;
align-items: center;
color: rgb(176, 58, 46);
background-color: #fdedec;
}
.navbar span { margin-right: auto; }
.logo { font-weight: 700; }
.nav__lists {
display: flex;
list-style: none;
column-gap: 2rem;
margin: 0 2rem;
}
#theme__switcher { cursor: pointer; }
main {
width: 300px;
margin: 5rem auto;
font-size: 2rem;
line-height: 2;
padding: 1rem 2rem;
border-radius: 10px;
box-shadow: 2px 3.5px 5px rgba(242, 215, 213, 0.4);
}После применения стилей интерфейс выглядит аккуратно и готов принимать тему.
Реализация тёмной темы: классы и переключение
Идея простая: назначаем для корня документа (body или html) класс .dark или .light и переключаем набор стилей через эти классы.
CSS‑классы для тем
.dark {
background: #1f1f1f;
color: #fff;
}
.light {
background: #fff;
color: #333;
}Рекомендация: в реальном проекте используйте CSS‑переменные (:root) и изменяйте только переменные в .dark / .light, чтобы покрыть все компоненты централизованно.
JavaScript: выбор элементов
В script.js сначала получаем ссылки на элементы управления:
// Получаем элементы для переключения темы
const themeToggle = document.getElementById("theme__switcher");
const bodyEl = document.body;JavaScript: функция установки темы и переключатель
Ниже — улучшенная и последовательная реализация setTheme, toggleTheme и обработчика клика. Код сохраняет выбор в localStorage и правильно меняет состояние переключателя.
// Установка темы: принимает строку "dark" или "light"
function setTheme(theme) {
bodyEl.classList.toggle("dark", theme === "dark");
bodyEl.classList.toggle("light", theme !== "dark");
// Визуально инвертируем иконку переключателя для обозначения тёмной темы
themeToggle.style.filter = theme === "dark" ? "invert(75%)" : "none";
// Сохраняем выбор пользователя
localStorage.setItem("theme", theme);
}
// Переключатель темы
function toggleTheme() {
setTheme(bodyEl.classList.contains("dark") ? "light" : "dark");
}
themeToggle.addEventListener("click", toggleTheme);Этот код гарантирует предсказуемое поведение и простоту тестирования.
Улучшения: учёт системных настроек и сохранение
Два важных улучшения: 1) учитывать системную тему пользователя, 2) хранить выбор в localStorage.
Детект предпочтений системы
Используем window.matchMedia и корректно переводим результат в “dark” или “light”:
function detectPreferredTheme() {
const prefersDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
// Возвращаем строку для setTheme
return prefersDarkMode ? "dark" : "light";
}Инициализация с учётом localStorage и системных настроек
Чтобы поддержать сохранённый выбор и при этом учитывать системные настройки для новых посетителей, используем следующую инициализацию:
// Попытка прочитать ранее сохранённую тему
const storedTheme = localStorage.getItem("theme");
if (storedTheme) {
setTheme(storedTheme);
} else {
// Если нет сохранённой темы — применяем системную предпочтительную
setTheme(detectPreferredTheme());
}Таким образом: пользовательский выбор имеет приоритет; если его нет — сайт соответствует настройкам ОС.
Практические рекомендации и проверочные сценарии
Важно: тёмная тема должна быть полной — проверьте все цвета кнопок, ссылок, границ, иконок и картинок. Ниже — полезные чеклисты и тесты.
Чеклист по ролям
Для дизайнера:
- Проверьте контраст текста и фона (минимум WCAG AA для текста).
- Подготовьте альтернативные версии иконок/изображений.
- Описать взаимодействие переключателя и состояния.
Для фронтенд‑разработчика:
- Использовать CSS‑переменные для тем;
- Обеспечить, чтобы фокусируемые элементы в тёмной теме видимы;
- Покрыть переключатель unit‑тестами/интеграцией.
Для QA:
- Проверить сохранение в localStorage;
- Проверить поведение при смене системной темы;
- Проверить контраст на разных разрешениях и устройствах.
Критерии приёмки
- При клике по #theme__switcher тема переключается и состояние сохраняется в localStorage;
- При отсутствии сохранённой темы используется prefers-color-scheme ОС;
- Все интерактивные элементы имеют достаточный контраст и видимый фокус;
- Иконки/изображения корректно отображаются в тёмной теме (альтернативы или фильтры).
Набор тестов (примеры)
- TC1: первый визит пользователя — ожидаемая тема = системная предпочтительная
- TC2: пользователь переключил на “dark” — при обновлении страницы тема остаётся “dark”
- TC3: при смене системной темы без сохранения — страница меняет тему при следующем заходе
- TC4: проверка контраста текста на компоненте X в тёмной теме
Альтернативные подходы и когда они уместны
- CSS Variables (предпочтительно): объявляете базовые цвета в :root и переписываете их в .dark. Это масштабируемо для больших проектов.
- Использовать data‑атрибут на (например, ) — удобно для серверной рендеринга и CSS селекторов.
- Серверная логика: сохранять выбор в профиле пользователя на сервере — полезно для авторизованных сервисов.
Контрпример: хранение только в куках старой реализации обычно избыточно — localStorage проще и быстрее для SPA.
Ментальные модели и эвристики
- Модель приоритета: user choice > server setting > system preference > default.
- Эвристика контраста: если фон тёмный, делайте акцент цветами для CTA, избегайте насыщенного чистого красного на тёмном фоне.
- Минимизация изменений: меняйте как можно меньше DOM при переключении, чтобы уменьшить мерцание.
Мини‑методология внедрения (4 шага)
- Спроектируйте цветовые переменные и иконки для обеих тем.
- Добавьте классы .dark/.light и настройте переменные.
- Реализуйте setTheme/toggleTheme и инициализацию с localStorage.
- Проведите QA по чеклисту и выкатите на тестовую среду.
Безопасность и приватность
Использование localStorage не передаёт пользователя идентифицирующие данные на сервер автоматически. Если вы решаете синхронизировать тему с сервером — сообщите пользователю и обеспечьте TLS.
Совместимость и миграция
- Для старых браузеров (IE11) localStorage доступен, но matchMedia может не поддерживаться — добавьте полифилы при необходимости.
- При миграции от ручных классов к CSS‑переменным — делайте это поэтапно с feature‑флагом.
Decision flow (Mermaid)
flowchart TD
A[Есть сохранённая тема в localStorage?] -->|Да| B[Применить saved theme]
A -->|Нет| C[Проверить prefers-color-scheme]
C -->|dark| D[Применить dark]
C -->|light| E[Применить light]
B --> F[Отобразить интерфейс]
D --> F
E --> FДоступность (accessibility)
- Проверяйте соотношение контраста (WCAG AA/AAA для важных элементов).
- Для анимаций учитывайте prefers‑reduced‑motion и не используйте резкие мигания при переключении темы.
- Обеспечьте видимый фокус (outline) для клавиатурной навигации.
Важно: тёмная тема — не только косметика; она должна улучшать опыт, а не ухудшать доступность.
Быстрый cheat‑sheet (сниппеты)
- Инициализация темы:
const stored = localStorage.getItem('theme');
if (stored) setTheme(stored); else setTheme(detectPreferredTheme());- CSS переменная:
:root { --bg: #fff; --text: #333; }
.dark { --bg: #1f1f1f; --text: #fff; }
body { background: var(--bg); color: var(--text); }Заключение и краткое резюме
Тёмная тема — легкий способ улучшить UX и адаптировать сайт под предпочтения пользователей. Реализация через CSS‑классы и простой JavaScript позволяет быстро внедрить переключатель, при этом учесть системные настройки и сохранить выбор пользователя.
Важно:
- используйте CSS‑переменные для масштабируемости;
- приоритет сохранённого выбора выше системного;
- не забывайте про доступность и тесты.
Ключевые шаги: подготовить переменные, добавить .dark/.light, реализовать setTheme/toggleTheme, покрыть тестами и проверить контраст.
Summary:
- Применяйте setTheme с параметром “dark”/“light”;
- Сохраняйте выбор в localStorage;
- Стройте проверки контраста и фокусных состояний;
- Рассмотрите синхронизацию с профилем пользователя для авторизованных сервисов.
Похожие материалы
Как пользоваться мультиметром — практическое руководство
Исправление разрывов изображения в Linux
Отключить рекламу на Samsung Galaxy — полное руководство
Как узнать устройства в Wi‑Fi через Nmap
Планирование питания с Eat This Much