Тёмная тема на сайте: как сделать правильно (CSS variables, prefers-color-scheme)

Тёмная тема на сайте: как сделать правильно (CSS variables, prefers-color-scheme)

Тёмная тема на сайте: как сделать правильно (CSS variables, prefers-color-scheme)

Тёмная тема перестала быть просто модным трендом — теперь это обязательная функция для любого современного сайта. Она снижает нагрузку на глаза в условиях слабого освещения, экономит заряд батареи на мобильных устройствах и просто предоставляет пользователям выбор. В этой статье мы разберём, как правильно реализовать тёмную тему, учитывая системные настройки и сохраняя выбор пользователя.

1. Подготовка: CSS-переменные для тем

Ключ к удобному переключению тем — использование CSS-переменных (custom properties). Они позволяют централизованно управлять цветовой схемой.

:root {
/* Цвета светлой темы */
	--bg-color: #ffffff;
	--text-color: #333333;
	--heading-color: #2c3e50;
	--section-bg: #f8f9fa;
	--shadow-color: rgba(0, 0, 0, 0.1);
}

[data-theme="dark"] {
  /* Цвета тёмной темы */
  --bg-color: #121212;
  --text-color: #e0e0e0;
  --heading-color: #bb86fc;
  --section-bg: #1e1e1e;
  --shadow-color: rgba(0, 0, 0, 0.3);
}

Совет по выбору цветов

Для тёмной темы лучше использовать не чистый чёрный (#000000), а тёмно-серые оттенки. Это снижает контраст и делает интерфейс более комфортным для глаз. Популярные варианты: #121212, #1e1e1e, #212121.

Применение переменных в CSS:

body {
	background-color: var(--bg-color);
	color: var(--text-color);
	transition: background-color 0.3s ease, color 0.3s ease;
}

h1, h2, h3 {
  color: var(--heading-color);
}

.card {
  background: var(--section-bg);
  box-shadow: 0 2px 4px var(--shadow-color);
}

2. Определение системных предпочтений

Медиазапрос prefers-color-scheme позволяет определить, какую тему — светлую или тёмную — предпочитает пользователь в настройках своей ОС.

/* Автоматическое применение тёмной темы */
@media (prefers-color-scheme: dark) {
	:root {
		--bg-color: #121212;
		--text-color: #e0e0e0;
		/* остальные переменные тёмной темы */
	}
}

Важное ограничение

Медиазапрос prefers-color-scheme не позволяет переопределить выбор пользователя на самом сайте. Для этого потребуется JavaScript.

Комбинированный подход:

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

/* Светлая тема по умолчанию */
:root {
	--bg-color: #ffffff;
	/* остальные переменные светлой темы */
}

/* Тёмная тема по системным настройкам */
@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		--bg-color: #121212;
		/* остальные переменные тёмной темы */
	}
}

/* Принудительная тёмная тема */
[data-theme="dark"] {
	--bg-color: #121212;
	/* остальные переменные тёмной темы */
}

/* Принудительная светлая тема */
[data-theme="light"] {
	--bg-color: #ffffff;
	/* остальные переменные светлой темы */
}

3. Переключатель темы с JavaScript

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

  1. Определять текущую тему (учитывая системные настройки)
  2. Переключать тему при клике
  3. Сохранять выбор пользователя (в localStorage)
  4. Восстанавливать выбор при загрузке страницы

HTML для переключателя:

<div class="toggle-container">
  <label class="toggle-switch">
      <input type="checkbox" id="theme-toggle">
      <span class="slider"></span>
  </label>
  <span id="theme-status">Тёмная тема</span>
</div>

JavaScript-код:

document.addEventListener('DOMContentLoaded', function() {
  const toggle = document.getElementById('theme-toggle');
  const themeStatus = document.getElementById('theme-status');
  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');

  // Проверяем сохранённую тему или системные настройки
  const currentTheme = localStorage.getItem('theme') || 
                      (prefersDark.matches ? 'dark' : 'light');

  // Применяем текущую тему
  if (currentTheme === 'dark') {
    document.documentElement.setAttribute('data-theme', 'dark');
    toggle.checked = true;
    themeStatus.textContent = 'Тёмная тема';
  } else {
    document.documentElement.setAttribute('data-theme', 'light');
    toggle.checked = false;
    themeStatus.textContent = 'Светлая тема';
  }

  // Обработчик переключения
  toggle.addEventListener('change', function() {
    if (this.checked) {
      document.documentElement.setAttribute('data-theme', 'dark');
      localStorage.setItem('theme', 'dark');
      themeStatus.textContent = 'Тёмная тема';
    } else {
      document.documentElement.setAttribute('data-theme', 'light');
      localStorage.setItem('theme', 'light');
      themeStatus.textContent = 'Светлая тема';
    }
  });

  // Следим за изменением системных настроек
  prefersDark.addEventListener('change', e => {
    if (!localStorage.getItem('theme')) {
      if (e.matches) {
        document.documentElement.setAttribute('data-theme', 'dark');
        toggle.checked = true;
        themeStatus.textContent = 'Тёмная тема';
      } else {
        document.documentElement.setAttribute('data-theme', 'light');
        toggle.checked = false;
        themeStatus.textContent = 'Светлая тема';
      }
    }
  });
});

4. Особенности дизайна для тёмной темы

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

Цветовые рекомендации:

  • Снижайте контраст — яркий текст на чисто чёрном фоне утомляет глаза
  • Используйте тёплые серые оттенки вместо холодных
  • Уменьшайте насыщенность цветов в тёмной теме на 10-20%
  • Избегайте чистого белого — используйте слегка приглушённые оттенки

Типографика:

  • Увеличьте межстрочный интервал (line-height) на 5-10%
  • Сделайте шрифт немного тоньше — жирные начертания могут "перегружать" тёмный интерфейс
  • Проверьте читаемость — контраст должен быть не менее 15:1 для основного текста

Тени и эффекты:

  • Замените тени на свечение — тени плохо видны на тёмном фоне
  • Используйте более прозрачные overlay-элементы
  • Добавьте тонкие границы для разделения элементов

5. Тестирование и специальные случаи

Тестирование в разных условиях:

  • Проверьте в разных браузерах — реализация может отличаться
  • Тестируйте на реальных устройствах — особенно на OLED-экранах
  • Проверьте системные настройки — изменяя тему ОС
  • Убедитесь в сохранении выбора после обновления страницы

Специальные элементы:

Некоторые элементы требуют особого внимания при реализации тёмной темы:

/* Стилизация scrollbar */
::-webkit-scrollbar {
    width: 10px;
}

::-webkit-scrollbar-track {
    background: var(--section-bg);
}

::-webkit-scrollbar-thumb {
    background: #555;
    border-radius: 5px;
}

::-webkit-scrollbar-thumb:hover {
    background: #888;
}

/* Стили для изображений в тёмной теме */
[data-theme="dark"] img {
    filter: brightness(0.9) contrast(1.1);
    opacity: 0.9;
}

/* Особые стили для SVG */
[data-theme="dark"] .icon {
  fill: #bb86fc;
}

Полезные ресурсы

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

Другие статьи

Самое интересное из мира технологий, полезные статьи и новости нашего агенства.
Организация CSS в 2026: BEM, Utility-first, CSS Modules, CSS-in-JS и современный CSS

Организация CSS в 2026: BEM, Utility-first, CSS Modules, CSS-in-JS и современный CSS

Полное руководство по выбору методологии организации CSS в 2026 году: сравнение подходов, примеры кода и рекомендации по выбору

Адаптивные таблицы 2026: 5 проверенных способов их создания

Адаптивные таблицы 2026: 5 проверенных способов их создания

Полное руководство по созданию адаптивных таблиц: от overflow-x до трансформации в карточки и CSS Grid.

GPT-5 Pro за 30 минут выполнила расчет скрытой симметрии Керра

GPT-5 Pro за 30 минут выполнила расчет скрытой симметрии Керра

GPT-5 Pro помогла с самой муторной частью — быстро «угадала форму» этих правил и подобрала коэффициенты так, чтобы все сходилось.

Все статьи

Остались вопросы?

Заполните форму ниже. Мы обязательно ответим вам в ближайшее время.

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