JavaScript · 7 минут

Тёмная тема с сохранением выбора пользователя

Добавим в сайт один переключатель: он учитывает системную тему при первом визите, запоминает ручной выбор и не сбрасывается после перезагрузки страницы.

Живой пример

Нажмите переключатель. Этот мини-интерфейс меняет палитру прямо сейчас и запоминает выбранный режим в браузере.

Ваш сервис

Личный кабинет

DeeNet приветствует тебя

Настройки остаются такими, какими их выбрал пользователь.

Активные проекты12

Зачем это нужно: тема — это настройка пользователя, а не одноразовая анимация. Поэтому её нужно сохранить и применить при следующем открытии сайта.

1. Добавьте кнопку

Разместите её в шапке сайта. Атрибут aria-pressed сообщает скринридеру, включена ли тёмная тема.

index.html
<button class="theme-toggle" type="button"
  aria-label="Переключить тему" aria-pressed="false">
  Тема
</button>

2. Опишите обе палитры через переменные

Не меняйте цвет у каждой кнопки отдельно. Вынесите основные цвета в CSS-переменные — тогда тема переключается одним атрибутом на корневом элементе.

style.css
:root {
  --bg: #f6f8fc;
  --text: #172033;
  --surface: #ffffff;
}

:root[data-theme="dark"] {
  --bg: #07101f;
  --text: #eef4ff;
  --surface: #101d33;
}

body {
  background: var(--bg);
  color: var(--text);
}

.card {
  background: var(--surface);
}

3. Сохраните выбор и подключите системную тему

Скрипт сначала берёт ранее сохранённый выбор. Если его ещё нет — смотрит системную настройку пользователя. Затем меняет атрибут data-theme на корневом элементе.

theme.js
const root = document.documentElement;
const button = document.querySelector('.theme-toggle');
const savedTheme = localStorage.getItem('theme');
const systemTheme = matchMedia('(prefers-color-scheme: dark)').matches
  ? 'dark'
  : 'light';

function setTheme(theme) {
  root.dataset.theme = theme;
  button.setAttribute('aria-pressed', theme === 'dark');
  localStorage.setItem('theme', theme);
}

setTheme(savedTheme || systemTheme);

button.addEventListener('click', () => {
  const nextTheme = root.dataset.theme === 'dark' ? 'light' : 'dark';
  setTheme(nextTheme);
});

Что проверить перед публикацией

  1. Переключатель меняет не только фон, но и текст, карточки, границы и ссылки.
  2. После перезагрузки сохраняется выбранная пользователем тема.
  3. При первом визите без сохранённого выбора тема берётся из настроек системы.
  4. Контраст текста остаётся читаемым в обоих режимах.

Где применять

Любой сайт с личным кабинетом или долгим чтением

Особенно полезно для блогов, дашбордов, документации и приложений, которыми пользуются вечером.

Ко всем гайдам