Автоматическое переключение тем сайта: настройка и внедрение
Для кого эта статья:
- Веб-разработчики и программисты
- UX-дизайнеры и специалисты по пользовательскому интерфейсу
Студенты и обучающиеся в области веб-разработки
Тёмная тема — это не просто модный тренд, а функционал, существенно повышающий удобство использования сайта. Представьте: пользователь заходит на ваш ресурс вечером, глаза устали, а тут — яркий белый экран буквально "выжигает" сетчатку! 🌙 Или наоборот: солнечным днём тёмная тема становится нечитаемой. Автоматическое переключение между светлой и тёмной темами — элегантное решение, которое превращает ваш сайт из просто хорошего в действительно заботящийся о пользователе. Давайте разберёмся, как реализовать это без лишних сложностей.
Погружаясь в мир автоматического переключения тем, вы делаете первый шаг к современной веб-разработке, где UX всегда на первом месте. На курсе Обучение веб-разработке от Skypro вы не просто научитесь создавать адаптивные интерфейсы — вы поймете, как мыслить категориями удобства пользователей. Здесь вы найдете баланс между эстетикой и функциональностью, осваивая инструменты, которые делают ваш код не просто рабочим, а впечатляющим.
Основы создания сайта с автоматическим переключением тем
Прежде чем приступить к кодированию, важно понять базовую архитектуру адаптивной темизации. Автоматическое переключение тем состоит из трёх ключевых компонентов:
- Система определения предпочтений пользователя (системные настройки или ручной выбор)
- Механизм хранения и применения выбранной темы
- Визуальное оформление для каждой темы (CSS-переменные и стили)
Современные браузеры позволяют определить, какую тему предпочитает пользователь на уровне операционной системы, благодаря медиа-запросу prefers-color-scheme. Это даёт возможность автоматически применять соответствующую тему при первом посещении сайта.
Однако для полноценного UX необходимо также предоставить возможность ручного переключения и сохранять этот выбор между сессиями, даже если он отличается от системных настроек.
Алексей Петров, Frontend-разработчик Однажды я работал над проектом для IT-компании, где большинство сотрудников использовали тёмную тему в своих редакторах кода. Когда мы запустили внутренний портал с документацией в традиционном светлом дизайне, начался настоящий бунт! Разработчики жаловались на "выжигание глаз" при переключении с IDE на наш портал.
Я быстро внедрил автоматическое определение темы по системным настройкам, и проблема была частично решена. Но затем обнаружилось, что некоторые пользователи предпочитают тёмную тему только для нашего портала, но не для всей системы. Это заставило меня реализовать полноценную систему с сохранением индивидуальных предпочтений.
Самым интересным стало то, что после внедрения двойной системы (авто + ручное управление) время, проводимое на портале, увеличилось на 22%. Оказалось, комфорт восприятия напрямую влияет на вовлечённость!
Для реализации темизации необходимо структурировать CSS так, чтобы изменение темы затрагивало минимум кода. Лучшее решение — CSS-переменные (Custom Properties), которые позволяют определить набор цветов для каждой темы и применять их ко всем элементам интерфейса.
| Подход | Преимущества | Недостатки |
|---|---|---|
| Отдельные CSS-файлы для тем | Чистое разделение кода, легко поддерживать | Дополнительные HTTP-запросы, сложнее анимировать переходы |
| CSS-переменные | Один файл стилей, плавные переходы, динамическое переключение | Не поддерживается в очень старых браузерах |
| Классы на body/html | Простая реализация, широкая поддержка | Сложнее поддерживать большие проекты, дублирование кода |

Реализация prefers-color-scheme для определения системной темы
Медиа-запрос prefers-color-scheme — это мощный инструмент, позволяющий узнать, предпочитает ли пользователь тёмную или светлую тему на уровне своей операционной системы. 🔍 Он имеет два основных значения: light и dark.
Базовая реализация в CSS выглядит так:
/* Стили для светлой темы (по умолчанию) */
:root {
--background: #ffffff;
--text: #333333;
--primary: #4285f4;
}
/* Стили для тёмной темы при системных настройках "тёмная тема" */
@media (prefers-color-scheme: dark) {
:root {
--background: #121212;
--text: #e0e0e0;
--primary: #8ab4f8;
}
}
С помощью JavaScript мы также можем определить предпочтения пользователя и реагировать на их изменение в реальном времени:
// Проверяем, предпочитает ли пользователь тёмную тему
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');
// Функция, которая будет вызываться при изменении настроек
function handleThemeChange(e) {
if (e.matches) {
// Пользователь предпочитает тёмную тему
document.body.classList.add('dark-theme');
} else {
// Пользователь предпочитает светлую тему
document.body.classList.remove('dark-theme');
}
}
// Вызываем функцию при загрузке
handleThemeChange(prefersDarkScheme);
// Добавляем слушатель на изменение настроек
prefersDarkScheme.addEventListener('change', handleThemeChange);
Это решение позволяет вашему сайту мгновенно адаптироваться к предпочтениям пользователя, создавая ощущение интеграции с операционной системой. Однако помните, что не все пользователи осведомлены о системных настройках темы, поэтому важно предоставить и ручное переключение.
Марина Соколова, UX-дизайнер В одном из проектов по редизайну финансовой платформы мы столкнулись с интересной проблемой. Статистика показывала, что большинство пользователей (около 65%) заходят на сайт в вечернее время, после работы. Многие жаловались на усталость глаз при просмотре бесконечных таблиц с цифрами на белом фоне.
Мы решили внедрить автоматическое переключение на тёмную тему после 19:00, основываясь на локальном времени пользователя. Это было ошибкой! Почти сразу появилось множество отзывов от людей, работающих в ярко освещённых помещениях вечером, для которых тёмная тема оказалась неудобной.
Переключившись на определение системных предпочтений через prefers-color-scheme, мы увидели рост удовлетворённости на 34%. Но настоящий прорыв случился, когда мы добавили ручной переключатель, который "помнил" выбор пользователя: показатели вовлечённости выросли на 40%, а среднее время сессии увеличилось на 3 минуты. Люди стали использовать сайт так, как им удобно, а не так, как мы решили за них.
Настройка CSS-переменных для светлой и тёмной темы
CSS-переменные (Custom Properties) — идеальный инструмент для управления темами сайта. Они позволяют определить все цветовые значения в одном месте и легко переопределить их при смене темы. 🎨
Вот расширенный пример организации переменных для двух тем:
:root {
/* Базовые цвета светлой темы */
--background-primary: #ffffff;
--background-secondary: #f5f5f5;
--text-primary: #333333;
--text-secondary: #666666;
--accent-color: #4285f4;
--border-color: #e0e0e0;
--shadow: rgba(0, 0, 0, 0.1);
/* Семантические переменные */
--success: #0f9d58;
--warning: #f4b400;
--error: #db4437;
/* Переходы для плавного изменения темы */
--transition-time: 0.3s;
}
/* Тёмная тема */
[data-theme="dark"] {
--background-primary: #121212;
--background-secondary: #1e1e1e;
--text-primary: #e0e0e0;
--text-secondary: #a0a0a0;
--accent-color: #8ab4f8;
--border-color: #333333;
--shadow: rgba(0, 0, 0, 0.3);
/* Семантические переменные для тёмной темы */
--success: #81c995;
--warning: #f9d949;
--error: #f28b82;
}
/* Применение переменных к элементам */
body {
background-color: var(--background-primary);
color: var(--text-primary);
transition: background-color var(--transition-time), color var(--transition-time);
}
.card {
background-color: var(--background-secondary);
border: 1px solid var(--border-color);
box-shadow: 0 2px 4px var(--shadow);
}
button.primary {
background-color: var(--accent-color);
color: white;
}
Такой подход позволяет создать целостную систему дизайна с учетом обеих тем. Важно помнить несколько принципов при работе с темами:
- Используйте семантические названия переменных, а не связанные с конкретными цветами
- Проверяйте контраст для обеих тем, особенно для текста и интерактивных элементов
- Добавляйте плавные переходы между темами с помощью CSS-transitions
- Не забывайте про изображения и графику — они также должны адаптироваться к темам
Для работы с изображениями в разных темах можно использовать CSS-фильтры или разные наборы изображений:
/* Инверсия для простой адаптации иконок к тёмной теме */
[data-theme="dark"] .icon {
filter: invert(1);
}
/* Или использование разных изображений для тем */
.logo {
background-image: url('logo-light.png');
}
[data-theme="dark"] .logo {
background-image: url('logo-dark.png');
}
| Элемент UI | Светлая тема | Тёмная тема | Рекомендации |
|---|---|---|---|
| Основной фон | #ffffff | #121212 | Не используйте абсолютно чёрный (#000000), предпочтительнее тёмно-серый |
| Карточки, элементы UI | #f5f5f5 | #1e1e1e | Обеспечьте лёгкое визуальное отличие от основного фона |
| Основной текст | #333333 | #e0e0e0 | Контраст с фоном должен быть минимум 4.5:1 по WCAG |
| Акцентный цвет | #4285f4 | #8ab4f8 | В тёмной теме часто требуется более светлый оттенок для того же цвета |
Создание интерактивного переключателя тем на JavaScript
Хотя автоматическое определение темы по системным настройкам — отличное начало, пользователям необходима возможность ручного выбора. Интерактивный переключатель решает эту задачу и повышает удобство использования сайта. 🔄
Базовая HTML-структура переключателя может выглядеть так:
<button id="theme-toggle" aria-label="Переключить тему">
<span class="light-icon">☀️</span>
<span class="dark-icon">🌙</span>
</button>
Теперь добавим JavaScript для функциональности:
// Получаем кнопку переключения
const themeToggle = document.getElementById('theme-toggle');
// Функция для переключения темы
function toggleTheme() {
// Проверяем текущую тему
const currentTheme = document.documentElement.getAttribute('data-theme');
// Определяем новую тему
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
// Применяем новую тему к HTML-элементу
document.documentElement.setAttribute('data-theme', newTheme);
// Сохраняем выбор пользователя в localStorage
localStorage.setItem('user-theme-preference', newTheme);
// Обновляем вид переключателя (опционально)
updateToggleAppearance(newTheme);
}
// Обновление внешнего вида переключателя
function updateToggleAppearance(theme) {
if (theme === 'dark') {
themeToggle.classList.add('dark-mode-active');
themeToggle.setAttribute('aria-pressed', 'true');
} else {
themeToggle.classList.remove('dark-mode-active');
themeToggle.setAttribute('aria-pressed', 'false');
}
}
// Добавляем обработчик события для кнопки
themeToggle.addEventListener('click', toggleTheme);
Для более продвинутого переключателя можно реализовать дополнительные опции:
- Анимированный переключатель (солнце/луна с плавной трансформацией)
- Радиокнопки с тремя вариантами: светлая, тёмная или системная тема
- Выпадающее меню с выбором из предустановленных цветовых схем
- Автоматическое переключение по времени суток
Ключевые аспекты, о которых стоит помнить при создании переключателя тем:
- Доступность – переключатель должен быть доступен с клавиатуры и работать с программами чтения с экрана
- Обратная связь – пользователь должен чётко понимать, какая тема активна в данный момент
- Производительность – переключение тем не должно вызывать заметных задержек или мерцаний
- Согласованность – все элементы интерфейса должны корректно изменяться при смене темы
Более современный подход к созданию переключателя с использованием CSS-анимации:
/* Стилизация переключателя */
.theme-toggle {
background: none;
border: none;
padding: 5px;
cursor: pointer;
position: relative;
overflow: hidden;
width: 40px;
height: 40px;
border-radius: 50%;
}
.toggle-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition: transform 0.5s, opacity 0.3s;
}
.sun-icon {
opacity: 1;
transform: translate(-50%, -50%) rotate(0);
}
.moon-icon {
opacity: 0;
transform: translate(-50%, -50%) rotate(-90deg);
}
/* Состояние при активной тёмной теме */
[data-theme="dark"] .sun-icon {
opacity: 0;
transform: translate(-50%, -50%) rotate(90deg);
}
[data-theme="dark"] .moon-icon {
opacity: 1;
transform: translate(-50%, -50%) rotate(0);
}
Сохранение выбора пользователя с помощью localStorage
Чтобы обеспечить по-настоящему качественный пользовательский опыт, необходимо сохранять выбранную тему между сессиями. Это позволит пользователям не переключать тему при каждом посещении сайта. 🔒
Механизм сохранения выбора реализуется через localStorage — это простой способ хранения данных в браузере пользователя:
// Функция для сохранения выбранной темы
function saveThemePreference(theme) {
localStorage.setItem('user-theme-preference', theme);
}
// Функция для получения сохранённой темы
function getSavedThemePreference() {
return localStorage.getItem('user-theme-preference');
}
// Функция для определения начальной темы
function getInitialTheme() {
// Проверяем, есть ли сохранённый выбор пользователя
const savedTheme = getSavedThemePreference();
if (savedTheme) {
// Возвращаем сохранённую тему
return savedTheme;
}
// Если нет сохранённого выбора, используем системные настройки
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
// По умолчанию – светлая тема
return 'light';
}
Теперь применим эту логику при загрузке страницы:
document.addEventListener('DOMContentLoaded', function() {
// Определяем начальную тему
const initialTheme = getInitialTheme();
// Применяем тему
document.documentElement.setAttribute('data-theme', initialTheme);
// Обновляем внешний вид переключателя
updateToggleAppearance(initialTheme);
// Добавляем слушатель для изменения системной темы
if (window.matchMedia) {
const colorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
// Функция-обработчик изменения системных настроек
const handleSystemThemeChange = function(event) {
// Проверяем, есть ли сохранённый выбор пользователя
const userPreference = getSavedThemePreference();
// Если пользователь не выбирал тему вручную, следуем системным настройкам
if (!userPreference) {
const newTheme = event.matches ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', newTheme);
updateToggleAppearance(newTheme);
}
};
// Добавляем слушатель
colorSchemeQuery.addEventListener('change', handleSystemThemeChange);
}
});
Этот подход создаёт трёхуровневую систему определения темы:
- Если пользователь явно выбрал тему — используется его выбор
- Если нет — используются системные настройки
- Если системные настройки недоступны — применяется светлая тема по умолчанию
Дополнительно можно рассмотреть несколько расширенных сценариев:
- Сброс темы до системной настройки (удаление пользовательского выбора)
- Тайм-аут для сохранённой темы (например, сбрасывать через месяц)
- Синхронизация выбора между разными страницами сайта
| Метод хранения | Преимущества | Ограничения | Срок хранения |
|---|---|---|---|
| localStorage | Простой API, без срока давности | Ограничение ~5MB, только строки | Пока пользователь не очистит данные |
| sessionStorage | Изолирован для вкладки | Удаляется при закрытии вкладки | Только текущая сессия |
| Cookie | Отправляется на сервер, гибкие настройки | Ограничение ~4KB, усложненный API | Настраиваемый (от сессии до лет) |
| IndexedDB | Большой объём, сложные структуры | Сложный API, избыточен для темы | Пока пользователь не очистит данные |
Для большинства сайтов localStorage является оптимальным вариантом благодаря простоте использования и длительному хранению данных. Однако в случае разработки приложения с серверной синхронизацией настроек пользователя, Cookie могут быть более подходящим выбором.
Реализация автоматического переключения тем на сайте — это не просто техническая фича, а проявление уважения к предпочтениям пользователей. Создавая такие адаптивные интерфейсы, вы демонстрируете внимание к деталям и заботу о комфорте посетителей. Каждый элемент — от медиа-запросов до localStorage — выполняет свою роль в создании целостного и гармоничного пользовательского опыта. Помните: лучший дизайн — тот, который незаметно подстраивается под потребности человека, делая технологии более человечными.