Темная тема перестала быть просто модным трендом — сегодня это ожидаемая пользователями функция, которая снижает нагрузку на глаза, экономит заряд батареи и просто выглядит стильно. В этом руководстве мы разберем, как грамотно реализовать переключение между светлой и темной темами на вашем сайте, используя современные подходы CSS и минимальное количество JavaScript.
Почему темная тема — это важно
Прежде чем переходить к технической реализации, стоит понять, зачем вообще нужна темная тема. Исследования показывают, что в условиях низкой освещенности темные интерфейсы снижают усталость глаз на 30-40%. Кроме того, на OLED-экранах темная тема может экономить до 60% заряда батареи. Но главное — вы даете пользователям выбор, что значительно улучшает пользовательский опыт.
Важно: Реализуя темную тему, не просто инвертируйте цвета. Продумайте цветовую палитру специально для темного режима, сохраняя контрастность и читаемость.
Базовый подход: CSS-переменные
Современный способ реализации темной темы основан на CSS-переменных (custom properties). Это позволяет централизованно управлять цветовой схемой и легко переключаться между темами.
Определяем цветовые схемы
Создадим две палитры — для светлой и темной тем:
:root {
/* Светлая тема (по умолчанию) */
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
--text-primary: #333333;
--text-secondary: #666666;
--accent-color: #4a90e2;
--border-color: #e0e0e0;
}
[data-theme="dark"] {
/* Темная тема */
--bg-primary: #121212;
--bg-secondary: #1e1e1e;
--text-primary: #ffffff;
--text-secondary: #b0b0b0;
--accent-color: #64b5f6;
--border-color: #333333;
}
Применяем переменные
Теперь используем эти переменные в стилях элементов:
body {
background-color: var(--bg-primary);
color: var(--text-primary);
transition: background-color 0.3s, color 0.3s;
}
.card {
background-color: var(--bg-secondary);
border: 1px solid var(--border-color);
}
.button {
background-color: var(--accent-color);
color: white;
}
JavaScript для переключения тем
CSS-переменные задали основу, но для переключения между темами нужен JavaScript. Вот минимальная реализация:
class ThemeSwitcher {
constructor() {
this.themeToggle = document.querySelector('#theme-toggle');
this.currentTheme = localStorage.getItem('theme') || 'light';
this.init();
}
init() {
this.setTheme(this.currentTheme);
if (this.themeToggle) {
this.themeToggle.addEventListener('click', () => {
this.toggleTheme();
});
}
}
setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
// Обновляем текст/иконку переключателя
if (this.themeToggle) {
this.themeToggle.textContent = theme === 'dark' ? '☀️' : '🌙';
}
}
toggleTheme() {
const newTheme = this.currentTheme === 'light' ? 'dark' : 'light';
this.currentTheme = newTheme;
this.setTheme(newTheme);
}
}
// Инициализация при загрузке страницы
document.addEventListener('DOMContentLoaded', () => {
new ThemeSwitcher();
});
Совет: Используйте localStorage для сохранения выбора пользователя. Это позволит сохранять тему между сессиями.
Учет системных предпочтений
Современные браузеры позволяют определять предпочтения пользователя через медиа-запрос prefers-color-scheme. Добавьте этот код в ваш JavaScript:
// Проверяем системные настройки
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && !localStorage.getItem('theme')) {
document.documentElement.setAttribute('data-theme', 'dark');
localStorage.setItem('theme', 'dark');
}
// Слушаем изменения системных настроек
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
if (!localStorage.getItem('theme')) {
const newTheme = e.matches ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', newTheme);
}
});
Продвинутые техники
Плавные переходы
Чтобы переход между темами был плавным, добавьте transition к основным свойствам:
* {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
Работа с изображениями
Для изображений можно использовать CSS-фильтры или загружать разные версии:
[data-theme="dark"] img:not(.no-filter) {
filter: brightness(0.8) contrast(1.2);
}
Темная тема для конкретных элементов
Иногда нужно исключить некоторые элементы из темной темы. Используйте специальный класс:
.keep-light {
background-color: white !important;
color: #333 !important;
}
Оптимизация производительности
При реализации темной темы учитывайте эти моменты:
- Минимизируйте количество перерисовок DOM при переключении темы
- Используйте CSS-переменные вместо дублирования стилей
- Кэшируйте выборку элементов DOM
- Избегайте layout thrashing при анимациях
Тестирование и доступность
Перед запуском обязательно протестируйте:
- Контрастность текста (минимальное соотношение 4.5:1)
- Читаемость шрифтов в обеих темах
- Работу темы на разных устройствах и браузерах
- Сохраняется ли выбор темы после перезагрузки
Важно: Убедитесь, что переключатель темы имеет достаточный контраст и понятную подпись для скринридеров.
FAQ — Часто задаваемые вопросы
Как сделать темную тему без мерцания при загрузке?
Добавьте скрипт установки темы в
страницы, перед загрузкой стилей. Это предотвратит FOUC (Flash Of Unstyled Content).Нужно ли поддерживать старые браузеры?
Для IE11 и старых браузеров используйте fallback-значения в CSS или полифиллы для CSS-переменных.
Как реализовать больше двух тем?
Используйте разные значения атрибута data-theme ("dark", "blue", "sepia") и соответствующие наборы CSS-переменных.
Влияет ли темная тема на SEO?
Нет, поисковые системы не учитывают цветовую тему сайта при ранжировании, но улучшенный пользовательский опыт может снизить показатель отказов.
Как протестировать доступность темной темы?
Используйте инструменты вроде axe DevTools или Lighthouse в Chrome DevTools, которые проверяют контрастность и другие параметры доступности.