Тёмная тема для любого сайта — 4 подхода на CSS
В твоей операционной системе тёмная тема есть уже годы. Браузер её поддерживает. Большинство приложений её уважают. Потом ты открываешь документацию, блог или интранет 2014 года — и получаешь в лицо стопроцентно белый фон в 23:00. Четыре способа решить это раз и навсегда.
Почему эта проблема существует
Стандарт CSS prefers-color-scheme есть в Chrome с 2019 года и в Safari с 2018-го. Твоя ОС знает твоё предпочтение, браузер его передаёт, сайты должны его уважать. Должны — на практике ~40% сайтов его игнорируют. Причины: легаси-кодовая база, нет бюджета на вторую тему, маркетинг хочет «согласованности бренда», автор просто до этого не дошёл.
Если автор не делает этого за тебя — сделай сам. Четыре способа, в порядке возрастания изящества.
Способ 1 — универсальный фильтр (работает на всём)
Один сниппет, подходит к любому сайту, никакого анализа конкретного CSS не нужно:
html {
filter: invert(0.92) hue-rotate(180deg);
background: #1a1a1a;
}
/* Ре-инвертируем изображения, видео и iframe, чтобы они
выглядели естественно — иначе селфи твоих друзей будут
с фильтром «зелёная кожа». */
img, video, picture, iframe, svg,
[style*="background-image"] {
filter: invert(1) hue-rotate(180deg);
}
Трюк: invert(0.92) вместо полного invert(1) даёт более мягкий чёрный, чем резкая замена белого на чёрный — это меньше утомляет глаза. hue-rotate(180deg) корректирует цвета, так что оранжевый остаётся оранжевым (а не становится синим).
Плюсы: работает везде, ноль анализа.
Минусы: тени, градиенты, нежные серые выглядят странно. Некоторые fixed-элементы (sticky-шапка) могут рассинхронизироваться при прокрутке.
Способ 2 — принудительный prefers-color-scheme: dark
Сайты, у которых есть тёмная тема, но они реагируют только на системное предпочтение. А если ты держишь ОС в светлом режиме (потому что проектируешь в Figma), но хочешь документацию GitHub в тёмном? Переопредели matchMedia:
// Принудительный prefers-color-scheme: dark через JS
const dark = window.matchMedia('(prefers-color-scheme: dark)');
Object.defineProperty(dark, 'matches', {
get: () => true,
configurable: true,
});
// Уведомляем слушателей (сайты, подключённые через addEventListener)
dark.dispatchEvent(new Event('change'));
Работает на любом сайте, который использует window.matchMedia('(prefers-color-scheme: dark)') для определения — все современные React/Vue-приложения. Не работает на сайтах, которые определяют тему один раз при загрузке (нужно было бы перезагрузить), или на статическом CSS без JS-определения.
Способ 3 — переопределение CSS custom properties
У сайтов, построенных на CSS-переменных (~60% современных веб-приложений), обычно есть токены темы вроде --bg-primary, --text-primary. Открой DevTools, найди имена, переопредели:
/* Пример: Stripe Dashboard, где всё построено на переменных */
:root {
--color-canvas-default: #0d1117 !important;
--color-canvas-subtle: #161b22 !important;
--color-fg-default: #c9d1d9 !important;
--color-fg-muted: #8b949e !important;
--color-border-default: #30363d !important;
}
Плюсы: точно, не портит изображения и тени.
Минусы: 5 минут раскопок в DevTools, чтобы найти имена переменных. Сайт должен использовать CSS-переменные (проверь: document.documentElement.style в консоли).
Способ 4 — отдельная тёмная тема для сайта
Для сайтов, на которых ты проводишь часы каждый день — 30 минут на индивидуальную тему стоят того. Выборочное переопределение:
/* Твой типичный корпоративный интранет */
body, .page-content, .sidebar, .top-bar {
background: #1a1a1a !important;
color: #e0e0e0 !important;
}
.card, .panel, .modal {
background: #242424 !important;
border-color: #333 !important;
}
a, a:visited { color: #58a6ff !important; }
a:hover { color: #79c0ff !important; }
input, textarea, select {
background: #1a1a1a !important;
color: #e0e0e0 !important;
border-color: #444 !important;
}
/* Таблицы — самое критичное для читаемости */
table th { background: #2d2d2d !important; color: #fff !important; }
table tr:nth-child(odd) { background: #1f1f1f !important; }
table tr:nth-child(even) { background: #1a1a1a !important; }
Начни с главных контейнеров (body, page), спускайся к компонентам (card, модальные окна), завершай элементами форм и таблицами. Без !important обычно не выиграешь — у сайта свои стили с более высокой специфичностью.
Частые ловушки
- Inline
background-image(например,style="background: url(...)") — фильтр способа 1 не всегда его ловит. Добавь[style*="background-image"]отдельно. - Тени на тёмном фоне выглядят как ореолы. Убери их (
box-shadow: none) или замени более светлым акцентом. - Цвета бренда (логотипы, цветные иконки) теряют узнаваемость после инверсии. Добавь исключения:
.brand-logo { filter: invert(1) hue-rotate(180deg) !important; }. - У форм часто захардкожен
color: blackв inline-стилях. Переопредели явно:input { color: #e0e0e0 !important; }. - Sticky / fixed элементы с фильтром способа 1 могут рассинхронизироваться при прокрутке. Обычно приемлемо, но об этом стоит знать.
Как подключить это к JustZix
- Установи JustZix (2 минуты).
- Создай папку под названием «Тёмная тема».
- Правило «Тёмная тема везде»: URL-паттерн
*, CSS = способ 1. Сделай его неактивным по умолчанию — включай, когда нужно. - Правило для любимого сайта: паттерн
https://myapp.com/*, CSS = способ 3 или 4 (с конкретными токенами / селекторами). Всегда активно. - Переключай всю папку одним кликом по плавающей кнопке — светлая/тёмная за один ход.
Что делать дальше
Та же иерархия (универсальное → точное для сайта) действует и в других категориях правил — смотри Примеры и Сценарии применения. Тёмная тема — лишь самый очевидный случай.
Установи JustZix бесплатно и наконец контролируй внешний вид сайтов, на которые смотришь 8 часов в день.
Оцени эту статью
Оценок пока нет — оцени первым.