Dark mode остается главной тенденцией в дизайне сайтов и приложений. Мы нашли классную статью на эту тему и решили поделиться переводом. Мнение пользователей, реализация и поддержка dark mode, рекомендации для разработчиков далее в статье. А на какой стороне вы?
Просто хайп или необходимость? Узнайте больше о темном режиме. Я расскажу, как добавить поддержку dark mode на благо ваших пользователей!
Введение
По данной теме я провел объемное исследование, изучил историю вопроса. Если вас интересует только работа с темным режимом, смело пропускайте первый раздел.
Темный режим до того, как это стало мейнстримом
![](https://habrastorage.org/webt/zj/bm/-3/zjbm-3ajwy7cak6sx5kjv27j-do.jpeg)
Говорят, история циклична. В ситуации с темным режимом мы вернулись к тому, с чего всё и начиналось. На заре эры персональных компьютеров использование темного режима было единственно возможным вариантом: монохромные ЭЛТ-мониторы работали, облучая пучками электронов фосфоресцирующий экран, а люминофор, использовавшийся в ранних ЭЛТ, был зеленым. Поскольку текст отображался зеленым цветом, а остальная часть экрана была черной, такие модели часто назывались зелеными экранами.
![](https://habrastorage.org/webt/6x/ee/fl/6xeeflgu-zfkfgbraqy67yypsua.jpeg)
Впоследствии цветные ЭЛТ-дисплеи стали отображать несколько цветов за счет использования красного, зеленого и синего люминофоров. Они создавали белый цвет, активируя все три люминофора одновременно. С появлением более современных настольных издательских систем и технологии WYSIWYG стала популярной идея сделать виртуальный документ похожим на реальный лист бумаги.
![](https://habrastorage.org/webt/qo/tm/e-/qotme-ob3eia59lsbbjlcxnguzs.png)
В этот момент в дизайне и зародился тренд «темное на белом», его реализовали в самых первых веб-сайтах сети — они больше походили на текстовые документы.
Первый в мире браузер WorldWideWeb (представьте, CSS еще не был изобретен) отображал веб-страницы именно так. Забавный факт: второй в истории браузер Line Mode Browser (браузер на основе терминала) был зеленым на темном. Сейчас веб-страницы и приложения обычно создаются с темным текстом на светлом фоне, что является общепринятой нормой. Такая цветовая схема встроена в таблицы стилей современных пользовательских агентов, включая, например, Chrome.
![](https://habrastorage.org/webt/ri/b0/io/rib0ioghgen4qr1ehwusxw2bvsg.jpeg)
Использование смартфонов (источник)
Дни ЭЛТ-мониторов давно прошли. Огромную часть контента теперь мы потребляем и создаем на мобильных устройствах, которые используют ЖК-дисплеи с подсветкой или энергосберегающие AMOLED-дисплеи. Меньшие по размеру и более практичные в использовании компьютеры, планшеты и смартфоны привели к новым моделям поведения пользователей. В свободное время мы пропадаем в социальных сетях, программируем ради развлечения или играем в компьютерные игры. Обычно это происходит после работы вечером при тусклом освещении или даже ночью в кровати перед сном. Чем больше людей пользуются девайсами в темноте, тем более популярным становится использование темного режима.
Почему мы выбираем темный режим?
По эстетическим соображениям
Когда людей спрашивают, почему им нравится темный режим, самые популярные ответы: «Он приятнее для глаз» или «Темный режим красивый». Компания Apple в документации для разработчиков темного режима открыто говорит: «Выбор темного или светлого интерфейса для большинства пользователей происходит на основе эстетических предпочтений и может не иметь отношения к условиям освещения».
Узнайте больше в исследовании, почему люди любят темный режим и как его используют.
![](https://habrastorage.org/webt/5r/th/0q/5rth0qg8-kwxynqtrxpdqvkqq30.png)
System 7 CloseView (источник)
Темный режим как инструмент доступности для людей с ограниченными возможностями здоровья
Некоторым людям использование темного режима просто необходимо: например, пользователи с ослабленным зрением используют такой режим как инструмент доступности. Самый ранний случай применения темного режима в качестве инструмента доступности, который я смог найти, — это функция CloseView в ОС System 7 с возможностью менять цветовую схему: черное на белом и белое на черном. Хотя System 7 поддерживала цветной интерфейс, пользовательский интерфейс по умолчанию оставался черно-белым.
Этот метод на основе инверсии, продемонстрировал свои слабые стороны после увеличения количества цветов в интерфейсе. Сарит Сзпиро (Sarit Szpiro) с командой исследователей провели опрос пользователей о том, как люди с ограниченным зрением обращаются с компьютерными устройствами. В результате оказалось, что все опрошенные не любили инвертированные цвета, но многие предпочитали светлый текст на темном фоне. Компания Apple учитывает данное предпочтение пользователей с помощью функции Smart Invert, которая меняет цвета на дисплее, за исключением изображений, мультимедиа и некоторых приложений, использующих стили темного цвета.
Особой формой слабовидения является синдром компьютерного зрения, также известный как цифровое напряжение зрения. Этими терминами обозначают различные проблемы со зрением, которые связаны с частым использованием компьютеров (настольные компьютеры, ноутбуки и планшеты) и других электронных устройств (смартфоны и электронные книги). Ученые предполагают, что использование подростками электронных устройств, особенно в ночное время, приводит к повышенному риску появления проблем со сном, бессонницы и синдрома недостаточности сна. Согласно другим исследованиям, воздействие синего света участвует в регуляции циркадного ритма и цикла сна, а нерегулярная световая среда может привести к депривации сна, что влияет на настроение человека и его эффективность при выполнении задач. Ограничить негативное влияние можно, уменьшив количество синего света с помощью регулировки цветовой температуры дисплея (такие функции, как iOS Night Shift или Android Night Light), а также предотвращая яркий или нерегулярный свет в целом благодаря темной теме или режиму.
Экономия энергии в темном режиме на AMOLED-дисплеях
Известно, что темный режим экономит много энергии на AMOLED-дисплеях. Исследования, посвященные популярным приложениям Google таким, как YouTube, доказали, что экономия энергии может достигать 60%. В видео ниже дана более подробная информация об этих исследованиях и экономии энергии для каждого приложения.
Как активировать темный режим в операционной системе
Теперь, когда я рассказал, почему темный режим так важен для многих пользователей, давайте рассмотрим, как вы можете его настроить.
![](https://habrastorage.org/webt/wm/ga/yn/wmgayn7k-5iqusbqrkhd8ilmnlc.png)
Настройки темной темы на Android Q
Операционные системы, поддерживающие темный режим или темную тему, обычно имеют возможность активировать их в настройках. В macOS X это находится в разделе «Общие» системных настроек и называется Appearance (снимок экрана), а в Windows 10 — в разделе Colors под названием Choose your color (снимок экрана). Для Android Q вы можете переключить режим в Display as a Dark Theme (снимок экрана), а в iOS 13 изменить цвет интерфейса можно в разделе Display & Brightness (снимок экрана).
Медиа-запрос prefers-color-scheme
Еще немного теории, прежде чем я продолжу. Медиа-запросы позволяют авторам тестировать и запрашивать значения и свойства пользовательского агента или устройства независимо от отрисовки документа. Они используются в CSS медиа-правиле для условного применения стилей к документу и в некоторых других контекстах и языках таких, как HTML и JavaScript. Медиа-запросы уровня 5 вводят так называемые предпочтительные для пользователя медиа-свойства, что является сигналом для сайтов обнаружить предпочтительный для юзера способ отображения контента.
Установленное CSS медиа-свойство prefers-reduced-motion может использоваться для определения того, запрашивает ли пользователь, чтобы ОС минимизировала количество анимации, которое она использует. Я уже писал о prefers-reduced-motion ранее.
CSS медиа-свойство prefers-color-scheme используется для определения, какая тема, светлая или тёмная, используется человеком в операционной системе. Оно работает со следующими значениями:
- no-preference: Указывает, что пользователь не сделал никаких предпочтений, известных системе. Это ключевое слово оценивается как ложное в логическом контексте.
- light: указывает, что пользователь уведомил систему, что он предпочитает страницу со светлой темой (темный текст на светлом фоне).
- dark: указывает, что пользователь уведомил систему, что он предпочитает страницу с темной темой (светлый текст на темном фоне).
Поддержка темного режима
Выясним, поддерживается ли темный режим браузером
Поскольку темный режим сообщается через медиа-запрос, вы можете легко проверить, поддерживает ли текущий браузер темный режим, выяснив, подходит ли медиа-запрос prefers-color-scheme. Обратите внимание, что я не устанавливаю значение, а просто проверяю медиа-запрос на соответствие.
if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
console.log(' Dark mode is supported');
}
На момент написания статьи prefers-color-scheme поддерживается как на настольных компьютерах, так и на мобильных устройствах (где доступно) в Chrome и Edge с версии 76, Firefox с версии 67 и Safari с версии 12.1 в macOS и с версии 13 на iOS. Для всех других браузеров информацию вы можете найти в статье Can I use support tables.
Доступен настраиваемый элемент <dark-mode-toggle>, который добавляет поддержку темного режима в старые браузеры. Об этом я напишу далее.
Темный режим на практике
Давайте рассмотрим, как на практике выглядит поддержка темного режима. Так же, как в фильме «Горец», в конце может остаться только один: темный или светлый! Почему я акцентирую на этом внимание? Потому что этот факт влияет на стратегию загрузки. Пожалуйста, не заставляйте пользователей скачивать CSS на критическом этапе рендеринга для режима, который сейчас не используется. Следовательно для оптимизации скорости загрузки я разделил мой CSS в примере на три части с целью отложить загрузку некритического CSS:
- style.css содержит общие правила, которые используются на всем сайте
- dark.css содержит правила, необходимые для темного режима
- light.css содержит правила, необходимые только для светлого режима.
Стратегия загрузки
Два последних, light.css и dark.css, загружаются выборочно через запрос <link media>.
Изначально не все браузеры поддерживают CSS медиа-свойство prefers-color-scheme (обнаруживаемое с помощью примера выше), это решается выбором light.css по умолчанию через элемент в нашем встроенном скрипте (light — это произвольный выбор, я также мог бы сделать dark по умолчанию). Чтобы избежать появления нестилизованного содержимого, я скрываю содержимое страницы до тех пор, пока не загрузится light.css.
<script>
// If `prefers-color-scheme` is not supported, fall back to light mode.
// In this case, light.css will be downloaded with `highest` priority.
if (window.matchMedia('(prefers-color-scheme)').media === 'not all') {
document.documentElement.style.display = 'none';
document.head.insertAdjacentHTML(
'beforeend',
'<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = ``">'
);
}
</script>
<!--
Conditionally either load the light or the dark stylesheet. The matching file
will be downloaded with `highest`, the non-matching file with `lowest`
priority. If the browser doesn't support `prefers-color-scheme`, the media
query is unknown and the files are downloaded with `lowest` priority (but
above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="/light.css" media="(prefers-color-scheme: no-preference), (prefers-color-scheme: light)">
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css">
Архитектура таблицы стилей
Я использую переменные CSS, что позволяет стилю style.css быть универсальным, вся настройка светлого или темного режима происходит в двух других файлах: dark.css и light.css. Ниже приведен пример, которого должно быть достаточно, чтобы объяснить общую идею. Я объявляю две переменные, --color и --background-color, которые создают основную тему «темный на светлом» и «светлый на темном».
/* light.css: dark-on-light */
:root {
--color: rgb(5, 5, 5);
--background-color: rgb(250, 250, 250);
}
/* dark.css: light-on-dark */
:root {
--color: rgb(250, 250, 250);
--background-color: rgb(5, 5, 5);
}
Затем в style.css я использую эти переменные в body {…}. Поскольку они определены в CSS псевдо-классе :root — селекторе, который в HTML представляет элемент <html> и идентичен селектору html, за исключением того, что его специфичность выше: переменные каскадно наследуются, таким образом позволяя определить глобальные CSS переменные.
/* style.css */
:root {
color-scheme: light dark;
}
body {
color: var(--color);
background-color: var(--background-color);
}
В приведенном выше примере вы, вероятно, заметили свойство color-scheme со значениями light dark, разделенными пробелом.
Свойство сообщает браузеру, какие цветовые темы поддерживает мое приложение, и позволяет ему активировать специальные варианты таблицы стилей пользовательского агента. Это полезно, например, для того, чтобы позволить браузеру отображать поля формы с темным фоном и светлым текстом, настраивать полосы прокрутки или чтобы включить цвет выделения с учетом темы. Детали свойства color-scheme указаны в CSS Color Adjustment Module Level 1.
Узнайте больше о color-scheme.
Все остальное — это просто определение CSS стилей для остальной разметки, которая есть на моем сайте. Семантическая организация стилей очень помогает при работе с темным режимом. Например, вместо --highlight-yellow рассмотрите возможность названия переменной --accent-color, так как «желтый» на самом деле может не быть желтым в темном режиме или наоборот. Ниже приведен пример еще нескольких переменных, которые я использую.
/* dark.css */
:root {
--color: rgb(250, 250, 250);
--background-color: rgb(5, 5, 5);
--link-color: rgb(0, 188, 212);
--main-headline-color: rgb(233, 30, 99);
--accent-background-color: rgb(0, 188, 212);
--accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
--color: rgb(5, 5, 5);
--background-color: rgb(250, 250, 250);
--link-color: rgb(0, 0, 238);
--main-headline-color: rgb(0, 0, 192);
--accent-background-color: rgb(0, 0, 238);
--accent-color: rgb(250, 250, 250);
}
Подробный разбор
В следующей вставке Glitch вы можете увидеть пример, в котором используется все, что описано выше, на практике. Попробуйте переключить темный режим в настройках вашей операционной системы и посмотрите, как отреагирует страница.
Влияние на скорость загрузки
Когда вы наиграетесь с этим примером, вы поймете, почему я загружаю свои dark.css и light.css через медиа-запросы. Попробуйте переключить темный режим и перезагрузить страницу: определенные, в настоящее время несовпадающие таблицы стилей все еще загружаются, но с самым низким приоритетом, чтобы они не конкурировали с ресурсами, которые необходимы сайту прямо сейчас.
Узнайте, почему браузеры загружают таблицы стилей с несовпадающими медиа-запросами.
Сайт в светлом оформлении загружает стили для темного оформления с самым низким приоритетом:
![](https://habrastorage.org/webt/bw/1k/qs/bw1kqsypxmaa4nts_oosemzaeyy.png)
Сайт в темном оформлении загружает стили для светлого оформления с самым низким приоритетом:
![](https://habrastorage.org/webt/bj/3b/je/bj3bje8wr5o3vwx0cjfwymo3f68.png)
Сайт по умолчанию в светлом оформлении в браузере, который не поддерживает prefers-color-scheme, загружает стили для темного оформления с самым низким приоритетом:
![](https://habrastorage.org/webt/dd/ai/fn/ddaifn724jsrqn3uda5rkru3npu.png)
Как реагировать на изменения темного режима
Как и на любое другое изменение медиа-запроса, на изменение темного режима можно подписаться через JavaScript. Вы можете использовать это, например, для динамического изменения значка страницы или изменения <meta name = "theme-color">, которое определяет цвет строки URL-адреса в Chrome. Пример выше показывает описанное в действии. Чтобы увидеть изменения цвета темы и значка, откройте демонстрацию в отдельной вкладке.
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addListener((e) => {
const darkModeOn = e.matches;
console.log(`Dark mode is ${darkModeOn ? ' on' : '️ off'}.`);
});
Лучшие практики темного режима
Избегайте абсолютно белого
Вы могли заметить маленькую деталь: я не использую чисто белый цвет. Вместо этого, чтобы предотвратить свечение на фоне окружающего темного содержимого, я выбрал немного более темный белый цвет, что-то вроде rgb (250, 250, 250).
Изменение цвета и затемнение фотоизображений
Если вы сравните два скриншота ниже, вы заметите, что не только основная тема изменилась с темного на светлом на светлый на темном, но и изображение выглядит немного иначе. Мой опрос показал, что большинство пользователей предпочитают чуть менее яркие и насыщенные изображения, когда активен темный режим. Я называю это перекрашиванием (re-colorization).
![](https://habrastorage.org/webt/bm/id/iy/bmidiy6w3vlbsvye5konmvpmito.png)
![](https://habrastorage.org/webt/2s/0p/pa/2s0ppaw_5q3jg75ci23hgvrchqk.png)
Перекрасить изображения можно с помощью фильтра CSS. Я использую селектор CSS, который подходит всем изображениям, не имеющим .svg в их URL-адресах. Идея заключается в том, что я могу дать векторной графике (иконкам) другую обработку, подробнее об этом в следующем разделе. Обратите внимание, как я снова использую переменную CSS, чтобы позже можно было быстро изменить свой фильтр.
Узнайте больше о предпочтениях пользователей из исследования.
Поскольку перекрашивание требуется только в темном режиме, то есть, когда dark.css активен, в light.css нет соответствующих правил.
/* dark.css */
--image-filter: grayscale(50%);
img:not([src*=".svg"]) {
filter: var(--image-filter);
}
Настройка интенсивности перекрашивания темного режима с помощью JavaScript
Мы разные, и у каждого человека будут свои представления, как именно должен выглядеть темный режим. Придерживаясь метода перекрашивания, описанного выше, я легко могу сделать интенсивность оттенков серого предпочтением пользователя, которое изменяется с помощью JavaScript, а установив значение 0%, я могу полностью отключить перекрашивание. Обратите внимание, что document.documentElement предоставляет ссылку на корневой элемент документа, то есть на тот же элемент, на который я могу ссылаться с помощью CSS псевдо-класса:root.
const filter = 'grayscale(70%)';
document.documentElement.style.setProperty('--image-filter', value);
Инвертировать векторную графику и иконки
Для векторной графики (в моем случае используется как иконки, на которые я ссылаюсь через элементы <img>) я использую другой метод перекрашивания. Хотя исследования показали, что людям не нравится инверсия фотографий, она очень хорошо работает для большинства иконок. Я снова использую переменные CSS для определения степени инверсии в обычном состоянии и в состоянии :hover.
Иконка инвертируется в темном режиме:
![](https://habrastorage.org/webt/9e/nf/hl/9enfhlmieghic6jxnm9wmad_gcc.png)
Иконка в светлом режиме:
![](https://habrastorage.org/webt/qs/er/uu/qseruulcgcfthfhcyvfankh4q6s.png)
Обратите внимание, как снова я инвертирую иконки только в dark.css, но не в light.css, и как :hover получает различную интенсивность инверсии в двух случаях, чтобы иконка выглядела немного темнее или немного ярче, в зависимости от режима, выбранного пользователем.
/* dark.css */
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);
img[src*=".svg"] {
filter: var(--icon-filter);
}
/* light.css */
--icon-filter_hover: invert(60%);
/* style.css */
img[src*=".svg"]:hover {
filter: var(--icon-filter_hover);
}
Используйте currentColor для inline SVG
Вместо использования инверсии фильтров для inline SVG изображений, вы можете добавить ключевое слово currentColor, которое представляет собой значение цвета элемента.
Это позволяет вам устанавливать значение цвета для свойств, которые не получают его по умолчанию. На самом деле, если currentColor используется как значение для атрибутов fill или stroke SVG, то он берет свое значение из унаследованного свойства цвета. Это также работает для <svg> <use href = "…"> </svg>, поэтому у вас могут быть отдельные ресурсы, а currentColor по-прежнему будет применяться в контексте. Обратите внимание, что это работает только для inline или <use href = "…"> SVG, но не для SVG, которые упоминаются как src изображения или через CSS. Подробнее здесь.
<!-- Some inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
>
[…]
</svg>
Плавные переходы между режимами
Переключение из темного режима в светлый или наоборот может быть сглажено благодаря тому факту, что цвет, и бэкграунд являются анимируемыми свойствами CSS. Создать анимацию так же просто, как объявить два перехода для двух свойств. Пример ниже иллюстрирует общую идею.
body {
--duration: 0.5s;
--timing: ease;
color: var(--color);
background-color: var(--background-color);
transition:
color var(--duration) var(--timing),
background-color var(--duration) var(--timing);
}
Художественное оформление с темным режимом
Хотя из соображений производительности загрузки в целом я рекомендую работать исключительно с prefers-color-scheme в атрибуте media элементов (а не встроенным в таблицы стилей), есть ситуации, когда вы действительно можете захотеть работать с prefers-color-scheme встроенным в ваш HTML-код. Художественное оформление — это как раз такая ситуация. Художественное оформление — общее визуальное оформление страницы: как сайт воздействует на пользователя, какие чувства вызывает.
В темном режиме дизайнер должен решить, какое изображение выбрать и будет ли перекрашивание изображений подходящим. При использовании элемента <picture> <source> отображаемого изображения можно сделать зависимым от атрибута media. В приведенном ниже примере я показываю западное полушарие для темного режима и восточное полушарие для светлого режима или, когда настройки не заданы, по умолчанию как для восточного полушария в любом случае. Изображения, конечно, просто иллюстрируют мой пример. Включите темный режим на своем устройстве, чтобы увидеть разницу.
<picture>
<source srcset="western.webp" media="(prefers-color-scheme: dark)">
<source srcset="eastern.webp" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)">
<img src="eastern.webp">
</picture>
Темный режим с возможностью отключения
Как упоминалось выше, большинство пользователей выбирают Dark Mode на основе своих вкусов и эстетических предпочтений. Некоторым пользователям нравится видеть UI своей ОС темным, а веб-страницы так, как они привыкли. План действий: сначала дождаться сигнала, который браузер отправляет через prefers-color-scheme, а затем позволить пользователям, если они хотят, переопределить настройки на уровне системы.
Кастомный элемент <dark-mode-toggle>
Вы, конечно, можете создать такой код самостоятельно, но можно просто использовать готовый элемент (веб-компонент), который я создал специально для этой цели. Он называется <dark-mode-toggle> и добавляет на вашу страницу переключатель (темный режим: вкл / выкл) или переключатель тем (тема: светлый / темный), который вы можете полностью настроить. Демо ниже показывает элемент в действии (о, и я незаметно использовал его во всех других примерах выше).
<dark-mode-toggle
legend="Theme Switcher"
appearance="switch"
dark="Dark"
light="Light"
remember="Remember this"
></dark-mode-toggle>
<dark-mode-toggle> в светлом режиме:
![](https://habrastorage.org/webt/u-/hy/np/u-hynpp7pkggfneg4p0vvjq9wzi.png)
<dark-mode-toggle> в темном режиме:
![](https://habrastorage.org/webt/z2/fj/kw/z2fjkwva2rhir_jzbid5p121th4.png)
Попробуйте щелкнуть или коснуться элементов управления темным режимом в верхнем правом углу в демонстрации ниже. Если вы установите флажки в третьем и четвертом элементах управления, посмотрите, как ваш выбор режима запоминается даже при перезагрузке страницы. Это позволяет вашим посетителям поддерживать свою операционную систему в темном режиме, но наслаждаться вашим сайтом в светлом режиме или наоборот.
Заключение
Работа с темным режимом и его поддержка — это весело! Открываются новые возможности для дизайна. Возможность выбора темного режима может сделать вашего пользователя более счастливым. Да, встречаются подводные камни, требуется тщательное тестирование, но темный режим — отличная возможность, чтобы показать заботу о пользователях. Лучшие практики, упомянутые в статье, и такой лайфхак, как настраиваемый элемент <dark-mode-toggle>, должны помочь вам в создании потрясающего темного режима.
Полезные ссылки
Медиа-запрос prefers-color-scheme:
Мета-тег color-scheme:
- Chrome Platform Status page
- Chromium bug
- CSS Color Adjustment Module Level 1 spec
- CSS WG GitHub Issue for the meta tag and the CSS property
- HTML WHATWG GitHub Issue for the meta tag
Ссылки о dark mode:
- Material Design — Dark Theme
- Dark Mode in Web Inspector
- Dark Mode Support in WebKit
- Apple Human Interface Guidelines — Dark Mode
Исследования: