Переходите на сторону light-dark()

Источник: «Come to the light-dark() Side»
За последние несколько лет интерфейсы с темным режимом сильно изменились. Все мы знаем традиционный подход с использованием медиа-запросов, но в этой статье Sara Joy демонстрирует современные CSS-функции, благодаря которым соблюсти предпочтения пользователя в выборе цветовой схемы становится чертовски просто.

Вас можно простить, если думаете, что кодировать одновременно тёмный и светлый режимы — это очень сложно. Нужно помнить о медиа-запросах на основе prefers-color-scheme, а также о дополнительных сложностях, возникающих, когда посетители могут выбирать светлый или тёмный режим отдельно от настроек ОС. И давайте не будем забывать о самой цветовой палитре! Переход от светлого режима к тёмному может потребовать новых вариаций, чтобы добиться нужного уровня контрастности для обеспечения доступности.

Это действительно большая работа. Но я хочу сказать, что с современным CSS это стало намного проще!

Цветовая схема HTML по умолчанию

Все знают голую тему HTML, даже если мы её редко видим, так как уже применили сброс CSS или наш любимый типовой CSS ещё до того, как открыли localhost. Но есть одна новость: в HTML есть не только стандартная чёрное на белом тема, но и нативная белое на чёрном.

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

See the Pen

Автоматическое переключение цветовых схем в зависимости от предпочтений ОС

Без каких-либо @media запросов — или вообще любого другого CSS — если объявить color-scheme: light dark для корневого элемента, страница автоматически применит светлую или тёмную цветовую схему, обратившись к предпочтениям операционной системы (ОС) посетителя. Большинство ОС имеют встроенную настройку доступности для предпочитаемой цветовой схемы — light, dark или даже auto — и браузеры уважают эту настройку.

html {
color-scheme: light dark;
}

Это можно сделать даже без CSS непосредственно в HTML-документе в теге <meta>:

<meta name="color-scheme" content="light dark">

Неважно, используете ли вы CSS или HTML — они работают одинаково: указывают браузеру, что нужно сделать доступными светлую и тёмную схемы и применить соответствующую предпочтениям посетителя. Даже не нужно засорять стили экземплярами prefers-color-scheme, чтобы просто поменять цвета, потому что логика уже встроена!

К свойству color-scheme можно применять значения light или dark. В то же время я бы сказал, что установка color-scheme: light является излишней, так как эта цветовая схема используется по умолчанию с объявлением или без него.

Конечно, можно управлять тегом <meta> или свойством CSS с помощью JavaScript.

Также есть возможность применить свойство color-scheme к определённым элементам, а не ко всей странице одним махом. Но, опять, это означает, что необходимо явно объявить свойства color и background-color элемента; в противном случае элемент будет прозрачным и унаследует цвет текста от родительского элемента.

Какие значения необходимо ему присвоить? Попробуйте:

Значения цвета текста и фона по умолчанию

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

Очень удобно то, что этот не чисто чёрный и не чисто белый цвет фона и цвет текста по умолчанию доступны как переменные <system-color>. Они также автоматически меняют свои цветовые значения с помощью color-scheme!

К ним относятся: Canvas и CanvasText.

Эти две переменные можно использовать в любом месте CSS для вызова текущего цвета фона по умолчанию (Canvas) или цвета текста (CanvasText) в зависимости от текущей цветовой схемы. Если вы знакомы со значением currentColor в CSS, то, похоже, оно функционирует аналогичным образом. CanvasText, тем временем, остаётся цветом текста по умолчанию, поскольку его нельзя изменить так, как меняется currentColor, когда вы присваиваете что-то color.

В следующих примерах изменяется только свойство color-scheme:

Скриншот кода и области вывода с color-scheme, установленным на light, большим div цвета фона Canvas с текстом внутри, установленным на цвет CanvasText, и div внутри него с поменянными местами Canvas и CanvasText.

Скриншот кода и области вывода с color-scheme, установленным на light, большим div цвета фона Canvas с текстом внутри, установленным на цвет CanvasText, и div внутри него с поменянными местами Canvas и CanvasText.

 Скриншот кода и области вывода с color-scheme, установленным на dark, остальной код тот же, а светлые и тёмные области поменялись местами.

Скриншот кода и области вывода с color-scheme, установленным на dark, остальной код тот же, а светлые и тёмные области поменялись местами.

Неплохо! Существует множество других системных переменных. Они не зависят от регистра и часто пишутся в camelCase или PascalCase для удобства чтения. В MDN перечислено 19 переменных <system-color>, и ниже для справки приводится их список.

Открыть, чтобы просмотреть 19 названий и описаний цветов системы
  • AccentColor: цвет фона для акцентированных элементов управления пользовательского интерфейса
  • AccentColorText: Цвет текста для акцентированных элементов управления пользовательского интерфейса
  • ActiveText: Цвет текста активных ссылок
  • ButtonBorder: Основной цвет границы для элементов управления
  • ButtonFace: Цвет фона для элементов управления
  • ButtonText: Цвет текста для элементов управления
  • Canvas: Цвет фона контента или документов приложения
  • CanvasText: Цвет текста, используемый в контенте или документах приложения
  • Field: Цвет фона для полей ввода
  • FieldText: Цвет текста в полях ввода формы
  • GrayText: Цвет текста для отключённых элементов (например, отключённого элемента управления).
  • Highlight: Цвет фона для выделенных элементов
  • HighlightText: Цвет текста для выделенных элементов
  • LinkText: Цвет текста, используемый для неактивных, непосещаемых ссылок
  • Mark: Цвет фона для текста, выделенного в элементе <mark>.
  • MarkText: Цвет текста, выделенного в элементе <mark>.
  • SelectedItem: цвет фона для выбранных элементов (например, выбранного чекбокса)
  • SelectedItemText: Цвет текста для выделенных элементов
  • VisitedText: Текст посещённых ссылок

Круто, правда? Их очень много! К сожалению, существуют также расхождения в том, как эти ключевые слова цвета используются и отображаются в разных ОС и браузерах. Несмотря на то, что вечнозелёные браузеры поддерживают их все, на самом деле не все они соответствуют тому, чему должны, и не могут работать с CSS свойством color-scheme так, как должны.

Egor Kloos (также известный как dutchcelt) следит за текущим состоянием системных цветов, в том числе за тем, какие из них существуют и какие браузеры их поддерживают. Он делает это в рамках бесклассового CSS-фреймворка под названием system.css.

See the Pen

Объявление цветов для обоих режимов вместе

Хорошо, теперь у нас есть страница, автоматически переключающая тёмные и светлые цвета в соответствии с системными предпочтениями. Использовать эти системные цвета или нет — решать вам. Хочу заметить, что тёмный не всегда означает чистый чёрный, так же как и светлый не означает чистый белый. Существует множество других цветов, сочетающихся между собой!

Но как лучше или проще всего объявить цвета, чтобы они работали и в светлом, и в тёмном режиме?

Мой субъективный рейтинг в обратном порядке:

Третье место: Объявление непрозрачности цвета

Вы можете сохранить все те же цвета фона в тёмном и светлом режимах, но объявить их с непрозрачностью (например, rgb(128 0 0 / 0,5) или #80000080). Тогда через них будет просвечивать цвет Canvas.

Этот способ не подходит для цветов текста, и в итоге могут получиться несколько приглушённые цвета. Но это хороший простой способ быстро создать темы. Я сделал это для блоков кода в старой демонстрации светлого и тёмного режимов.

Скриншот сайта, разделённого на тёмный и светлый режимы, показывает блоки кода с нежными цветами фона, разделённые на оба режима
Скриншот сайта, разделённого на тёмный и светлый режимы, показывает блоки кода с нежными цветами фона, разделённые на оба режима

Второе место: Использование color-mix()

Например, так:

color-mix(in oklab, Canvas 75%, RebeccaPurple);

Аналогично (но и по другому) использованию непрозрачности для приглушения цвета можно смешивать цвета в CSS. Можно даже смешивать системные цветовые переменные! Например, один из цветов может быть либо Canvas, либо CanvasText, чтобы цвет фона всегда смешивался с Canvas, а цвет текста — с CanvasText.

Теперь есть CSS функция color-mix(), помогающая в этом. Первый аргумент функции определяет цветовое пространство, в котором происходит смешивание цветов. Например, можно указать функции, что мы работаем в цветовом пространстве OKLAB, представляющем собой прямоугольное цветовое пространство, подобное sRGB, что делает его идеальным для смешивания с цветовыми значениями sRGB для получения предсказуемых результатов. Конечно, можно смешивать цвета из разных цветовых пространств — в данном случае мне подошла комбинация OKLAB/sRGB.

Второй и третий аргументы — это цвета, которые необходимо смешать, и в какой пропорции. Пропорции необязательны, но выражаются в процентах. Без указания пропорции смесь будет иметь равномерное соотношение 50% на 50%. Если при добавлении процентов для обоих цветов они в сумме не дают 100%, программа немного посчитает за вас, чтобы предотвратить поломку.

Подход color-mix() удобен, если необходимо сохранить одинаковые оттенки и насыщенность цветов независимо от того, светлый или тёмный режим.

 Скриншот сайта whimsica11y.net, использующего метод color-mix() для создания темы

Скриншот сайта whimsica11y.net, использующего метод color-mix() для создания темы

В этом примере при изменении значения ползунка hue вы увидите изменения цвета в темизированных блоках, повторяющие цвет темы, но смешанные с Canvas и CanvasText:

See the Pen

Возможно, вы заметили, что в последнем примере использованы цветовые пространства OKLCH и HSL. Вы также могли заметить, что цвет темы на основе HSL и темизированный абзац становятся более яркими, во время движения ползунка hue.

Я объявлял цвета, используя полярное цветовое пространство, такое как HSL, в течение многих лет, любя, что можно легко взять оттенок и увеличить или уменьшить шкалу насыщенности и светлости в зависимости от необходимости. Но согласен, что проблематично работая с несколькими оттенками, пытаться добиться одинаковой воспринимаемой светлости и насыщенности для всех. С HSL бывает сложно обеспечить достаточный контраст по всему спектру цветов.

Цветовое пространство OKLCH также полярно, как и HSL, с теми же преимуществами. Можно выбрать оттенок и использовать значение цветности (что немного похоже на насыщенность в HSL), а светлость точно так же масштабируется. И OKLCH, и OKLAB разработаны для лучшего соответствия тому, что воспринимают наши глаза в плане яркости и цвета, по сравнению с переходом между цветами в пространстве sRGB.

Хотя эти цветовые пространства не могут однозначно ответить на извечный вопрос: Мой синий такой же, как ваш синий?, цвета в них гораздо более последовательны и требуют меньше доработок, когда решено основывать палитру сайта на другом цвете темы. При использовании этих цветовых пространств контрасты между вычисляемыми цветами остаются неизменными.

Первое место (победитель!): Используйте light-dark()

Например, так:

light-dark(lavender, saddlebrown);

В предыдущем примере с color-mix(), если выбрать бледно-лавандовый цвет в светлом режиме, то его аналог в тёмном режиме будет очень темно-лавандовым.

Функция light-dark(), наоборот, обеспечивает полный контроль. Хотите, чтобы в светлом режиме этот элемент был бледно-лавандовым, а в тёмном — темно-коричневым. Почему бы и нет? Можно использовать функцию color-mix() в функции light-dark(), если хочется — объявляйте цвета как угодно и получайте гораздо более тонкий контроль над ними.

Не стесняйтесь экспериментировать в этой демонстрации:

See the Pen

Использование color-scheme: light dark; — или соответствующего метатега в HTML на странице — является обязательным условием для функции light-dark(), поскольку позволяет ей учитывать системные предпочтения человека, или любое другое значение светлого или тёмного, установленное вами в color-scheme.

Ещё одно соображение заключается в том, что функция light-dark() доступна в браузерах недавно, и на момент написания этой статьи её охват составляет чуть более 80% для всех пользователей. Поэтому можно предусмотреть возможность включения в CSS запасного варианта для браузеров, не поддерживающих эту функцию.

Чем использование color-scheme и light-dark() лучше @media запросов

@media запросы были отличными инструментами, но их использование для запроса prefers-color-scheme всегда соответствует предпочтениям, установленным в операционной системе пользователя. Это хорошо, пока вы (по праву) не захотите предложить посетителю больше возможностей выбора, не зависящих от того, предпочитает ли он, чтобы пользовательский интерфейс на его устройстве был темным или светлым.

Конечно, мы уже умеем это делать. Мы уже привыкли к тому, что для этого нужно много возиться с дополнительными классами CSS, использовать дублирование стилей или применять CSS переменные.

Радость от использования color-scheme тройная:

Управление светлым, темным и автоматическим режимами

По сути, всё, что мы делаем, это устанавливаем один из трёх вариантов того, является ли color-schemelight, dark или обновляется автоматически.

Я советую предлагать все три варианта как отдельные опции, поскольку это избавит от ряда сложностей! Любой новый посетитель сайта, скорее всего, перейдёт в авторежим, потому что принятие настроек ОС посетителя — это наименее раздражающее состояние по умолчанию. Затем дайте посетителю выбор: остаться в этом режиме или поменять его на другую цветовую схему. Таким образом, не нужно выяснять, какой режим предпочитает человек, чтобы, например, отобразить правильную иконку на тумблере и заставить его выполнить нужное действие. Также нет необходимости держать слушателя событий на prefers-color-scheme на случай изменений — объявление color-scheme: light dark в CSS сделает это за вас.

Три примера переключателей режимов, каждый из которых имеет три варианта: Auto, Light и Dark. Кнопки, набор полей с радиокнопками и элемент select.

Три примера переключателей режимов, каждый из которых имеет три варианта: Auto, Light и Dark. Кнопки, набор полей с радиокнопками и элемент select.

Настройка color-scheme в чистом CSS

Да, это вполне возможно! Но этот подход имеет несколько оговорок:

Использование псевдо-селектора :has()

Этот подход почти пугающе прост и отлично подходит для простого одностраничника! Большая часть тяжёлой работы уже выполнена:

/* по умолчанию, или 'auto' */
html {
color-scheme: light dark;
}

html:has([value="light"]:checked) {
color-scheme: light;
}

html:has([value="dark"]:checked) {
color-scheme: dark;
}

Второй и третий наборы правил ищут атрибут value у любого элемента, которому присвоено значение light или dark, а затем изменяют color-scheme на соответствующий, только если этот элемент имеет значение :checked.

Такой подход не очень эффективен, если у вас огромная страница, полная элементов. В таких случаях лучше быть более конкретным. В следующих двух примерах селекторы CSS проверяют значение только в элементе, содержащем id="mode-switcher".

html:has(#mode-switcher [value="light"]:checked) { color-scheme: light }
/* А вы знали, что для однострочников не нужен символ ";"? Теперь знаете! */

Использование элемента <select>:

See the Pen

Использование <input type="radio">:

See the Pen

Теоретически для этого можно использовать чекбоксы, но поскольку чекбоксы не предназначены для взаимоисключающих опций, не буду приводить пример. Что произойдёт в случае, если будет отмечено более одной опции? Побеждает последнее подходящее объявление CSS (в примерах выше это dark).

Настройка color-scheme в HTML с помощью JavaScript

Я придерживаюсь максимы Jeremy Keith, когда дело доходит до JavaScript:

JavaScript должен делать только то, что может делать только JavaScript.

Это именно такая ситуация.

Если хотите позволить посетителям менять цветовую схему с помощью кнопок, или хотите, чтобы опция сохранялась при следующем посещении сайта, то нужно хотя бы немного JavaScript. Вместо того чтобы использовать псевдо-селектор :has() в CSS, существует несколько альтернативных подходов к изменению color-scheme, если добавить JavaScript.

Использование тегов <meta>

Если задать color-scheme в метатеге в <head>:

<meta name="color-scheme" content="light dark">

… для начала можно создать удобную константу, например, так:

const colorScheme = document.querySelector('meta[name="color-scheme"]');

А затем можно манипулировать ей, назначая светлую или тёмную тему по своему усмотрению:

colorScheme.setAttribute("content", "light"); // в светлый режим
colorScheme.setAttribute("content", "dark"); // в тёмный режим
colorScheme.setAttribute("content", "light dark"); // в автоматический режим

Этот подход очень похож на использование тегов <meta>, но отличается от него, если свойство color-scheme задаётся в CSS:

html { color-scheme: light dark; }

Вместо установки константы colorScheme, как это было сделано в предыдущем примере с помощью тега <meta>, можно выбрать элемент <html>:

const html = document.querySelector('html');

Теперь манипуляции выглядят следующим образом:

html.style.setProperty("color-scheme", "light"); // в светлый режим
html.style.setProperty("color-scheme", "dark"); // в тёмный режим
html.style.setProperty("color-scheme", "light dark"); // в автоматический режим

Мне нравится превращать эти манипуляции в функции, позволяющие использовать их повторно:

function switchAuto() {
html.style.setProperty("color-scheme", "light dark");
}
function switchLight() {
html.style.setProperty("color-scheme", "light");
}
function switchDark() {
html.style.setProperty("color-scheme", "dark");
}

В качестве альтернативы, возможно, вы захотите остаться DRY, насколько это возможно, и сделать что-то вроде этого:

function switchMode(mode) {
html.style.setProperty("color-scheme", mode === "auto" ? "light dark" : mode);
}

В следующей демонстрации показано, как подход на основе JavaScript можно использовать с кнопками, радиокнопками и элементом <select>. Обратите внимание, что не все элементы управления подключены для обновления UI — демонстрация получилась бы слишком сложной, поскольку не существует мира, в котором все три типа элементов управления использовались бы в одном и том же UI!

See the Pen

Запоминание выбора для повторных посещений

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

Для этого используем Web Storage API. Есть два доступных способа сохранить чьи-то предпочтения по цветовой схеме для будущих посещений.

localStorage

Локальное хранилище сохраняет значения непосредственно на устройстве посетителя. Это хороший способ не привязываться к серверу, поскольку срок хранения данных никогда не истекает, что позволяет обращаться к ним в любое время. Тем не менее эти данные могут быть потеряны, когда посетитель очистит куки и кэш, и ему придётся делать новый выбор, заново сохраняемый в localStorage.

Выберите имя ключа и присвойте ему значение с помощью .setItem():

localStorage.setItem("mode", "dark");

Ключ и значение сохраняются браузером и могут быть вызваны при последующих посещениях:

const mode = localStorage.getItem("mode");

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

sessionStorage

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

Это очень похоже на localStorage:

sessionStorage.setItem("mode", "dark");
const mode = sessionStorage.getItem("mode");

Какой метод хранения использовать

Я начал с использования sessionStorage, потому что хотел, чтобы мой сайт был как можно более простым, и чтобы избежать всего, что могло бы вызвать необходимость в баннере куки, соответствующем GDPR, если бы сохранялись предпочтения человека после окончания его сессии. Если большая часть трафика поступает от новых посетителей, то я рекомендую использовать sessionStorage, чтобы избежать лишней работы с GDPR.

Однако если ваш трафик состоит в основном из людей, возвращающихся на сайт снова и снова, то лучше использовать localStorage. Удобство выгодно вашим посетителям, поэтому работа с GDPR стоит того.

Следующий пример демонстрирует подход localStorage. Откройте его в новом окне или вкладке, выберите тему, отличающуюся от установленной в настройках операционной системы, закройте окно или вкладку, а затем снова откройте демонстрацию в новом окне или вкладке. Соблюдает ли демонстрация выбранную вами цветовую схему? Должна!

See the Pen

Выберите опцию « Auto», чтобы вернуться к обычному режиму.

Если хотите посмотреть на происходящее более внимательно, откройте инструменты разработчика в браузере (F12 для Windows, CTRL + click и выберите Inspect в macOS). Оттуда перейдите на вкладку Application и найдите https://cdpn.io в списке элементов, сохранённых в localStorage. Вы увидите сохранённый ключ (mode) и значение (dark или light). Затем снова начните кликать по опциям цветовой схемы и наблюдайте за обновлением режима в режиме реального времени.

Снимок экрана верхней части Edge devtools с открытой вкладкой Application. Показан ключ `mode` и значение `dark`, сохранённые в локальном хранилище cdpn.io.

Снимок экрана верхней части Edge devtools с открытой вкладкой Application. Показан ключ mode и значение dark, сохранённые в локальном хранилище cdpn.io.

Доступность

Поздравляем! Если вы дошли до этого момента, значит, вы рассматриваете или уже предоставляете версии своего сайта, удобные для использования разными людьми.

Например:

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

Уровни контраста

Я хочу добавить небольшое дополнение к положению о светлом и тёмном режиме. Существует искушение сделать полный монохром — чёрное на белом или белое на чёрном. Это бросается в глаза и выглядит эффектно! Я понимаю. Но в том-то и дело, что у некоторых людей, которые гораздо лучше чувствуют себя при более низком контрасте, это может вызвать мигрень.

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

К счастью, наряду с другими медиа-запросами мы также можем задать запрос prefers-contrast, принимающий значения no-preference, more, less или custom.

В следующем примере (использующем :has() и color-mix()) отображается элемент <select>, предлагающий настройки контрастности. При выборе значения Low ко всей странице применяется фильтр contrast(75%). Если выбрано значение High, то для цвета текста и фона используются несмешанные цвета CanvasText и Canvas:

See the Pen

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

ARIA-pressed

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

Слова там, где это необходимо выполняют тяжёлую работу. Говорят, что, как и в случае с апострофами, отсутствие ARIA лучше, чем плохое ARIA. Поэтому лучше всего не ставить её везде. По большей части (за редким исключением) родные HTML-элементы вполне пригодны для использования, особенно если поместить в кнопки полезный текст!

Немного ARIA используется в этой демонстрации для добавления атрибута aria-pressed к кнопкам, поскольку, в отличие от радио группы или элемента select, неясно, какая кнопка является активной, и ARIA хорошо помогает в этом случае. Теперь устройство чтения с экрана будет сообщать вместе с кнопкой и её доступное имя, и то, в каком состоянии она находится — нажатом или не нажатом.

Ниже приведён пример фрагмента кода, в котором весь код ARIA выделен — да, неожиданно много! Можно найти более изящные (или более DRY-шные) способы сделать это, но сначала продемонстрируем таким образом, чтобы было понятнее, что происходит.

У кнопок есть идентификаторы, используемые для их нацеливания с помощью нескольких удобных констант в верху. Каждый раз, когда переключается режим, значение aria-pressed кнопки для выбранного режима становится true, а два других — false:

const html = document.querySelector("html");
const mode = localStorage.getItem("mode");
const lightSwitch = document.querySelector('#lightSwitch');
const darkSwitch = document.querySelector('#darkSwitch');
const autoSwitch = document.querySelector('#autoSwitch');

if (mode === "light") switchLight();
if (mode === "dark") switchDark();

function switchAuto() {
html.style.setProperty("color-scheme", "light dark");
localStorage.removeItem("mode");
lightSwitch.setAttribute("aria-pressed","false");
darkSwitch.setAttribute("aria-pressed","false");
autoSwitch.setAttribute("aria-pressed","true");
}

function switchLight() {
html.style.setProperty("color-scheme", "light");
localStorage.setItem("mode", "light");
lightSwitch.setAttribute("aria-pressed","true");
darkSwitch.setAttribute("aria-pressed","false");
autoSwitch.setAttribute("aria-pressed","false");
}

function switchDark() {
html.style.setProperty("color-scheme", "dark");
localStorage.setItem("mode", "dark");
lightSwitch.setAttribute("aria-pressed","false");
darkSwitch.setAttribute("aria-pressed","true");
autoSwitch.setAttribute("aria-pressed","false");
}

При загрузке кнопки устанавливаются по умолчанию, когда активна кнопка режима Auto. Если в локальном хранилище хранится какой-либо другой режим, мы сразу подхватываем его и запускаем либо switchLight(), либо switchDark(), оба из которых содержат изменения aria-pressed, относящиеся к этому режиму.

<button id="autoSwitch" aria-pressed="true" type="button" onclick="switchAuto()">Auto</button>
<button id="lightSwitch" aria-pressed="false" type="button" onclick="switchLight()">Light</button>
<button id="darkSwitch" aria-pressed="false" type="button" onclick="switchDark()">Dark</button>

Ещё одно преимущество aria-pressed заключается в том, что его можно использовать для стилизации:

button[aria-pressed="true"] {
background-color: transparent;
border-width: 2px;
}

Наконец, у нас есть маленькая симпатичная кнопка-переключатель, её состояние чётко отображается и объявляется, и она запоминает ваш выбор, когда вы к ней возвращаетесь. Готово!

See the Pen

Заключение

Или что там противоположно вступлению…

… не позволяйте втянуть себя в старый спор между темным и светлым режимом. Оба варианта хороши. Оба великолепны! И оба режима теперь можно легко создать одновременно. Начиная следующий проект, работу или хобби, не поддавайтесь страху не выбирайте сторону — попробуйте и то, и другое, и дайте возможность выбора.

Комментарии


Дополнительные материалы

Предыдущая Статья

Улучшение производительности с делегированием событий

Следующая Статья

Новое в Symfony 7.2: Опциональный секрет