Одной из последних тенденций на веб-сайтах (и в приложениях) является Темный режим. В темном режиме веб-сайты (и приложения) выглядят темными (!!!), как правило, с темным фоном, светлым текстом и некоторыми акцентными цветами. Многие компании теперь требуют, чтобы эта функция присутствовала в их интерфейсах, поскольку темный режим может уменьшить расход заряда батареи (особенно на мобильных телефонах с OLED), его можно лучше читать при слабом освещении, считается, что он помогает людям с нарушениями зрения лучше читать и многое другое. .

Как работает рабочий процесс темного режима (обычно)

Когда вы посещаете сайт, сам сайт должен проверить, есть ли у вас сохраненные настройки, и в соответствии с ними, показывая правильный режим, если у вас нет предпочтений, он должен проверить, поддерживает ли ваша ОС темный режим, и он у вас включен. , активируйте правильный режим (или режим по умолчанию) и сохраните настройку на клиенте. Он также должен дать пользователю возможность изменить свои предпочтения.

Почему темный режим может быть сложным для Гэтсби

Если сайт проверяет клиент, когда DOM уже отрендерен (или отрисовывается), а затем активирует темный режим (при необходимости), экран будет мерцать из режима по умолчанию в темный режим (да, Youtube мерцает из светлого режима в темный режим !). Нам нужно реализовать проверки с помощью блокирующих скриптов до того, как тело начнет отображаться. В Gatsby (да и вообще в любом статическом генераторе) у нас нет доступа к этой части страницы, поэтому нам нужно внедрить код во время компиляции с помощью gatsby-ssr.js . Мы также должны быть уверены, что наш внедренный скрипт действительно работает, поскольку мы блокируем рендеринг, пока читаем/записываем пользовательские настройки.

Что будем внедрять

Прежде всего, мы пишем скрипт, который будет внедрен в наш заголовок во время создания сайта, он позаботится о чтении пользовательских настроек из LocalStorage или из настроек цветовой схемы ОС, если это необходимо, в случае, если пользователю нужна темная тема, он добавит класс dark на уровне ‹html›, затем этот класс можно будет использовать для переключения между переменными CSS или для реализации их темной темы с помощью среды CSS (например, Tailwind поддерживает Dark Theme с использованием классовой стратегии). После этого мы собираемся реализовать компонент, который мы можем использовать на нашем сайте, который позволяет пользователю переключать режим и сохранять настройки.

Предпосылки

Чтобы следовать, вам нужно хотя бы иметь базовые знания React JS, Gatsby (и его файловой структуры и SSR API), немного CSS/SCSS. Вы также можете клонировать репозиторий для этого проекта.

Гэтсби Проект

Настройте новый проект Gatsby:

npm init gatsby

выберите и установите нужные вам плагины и библиотеки, затем войдите в папку проекта и запустите:

gatsby develop

Вновь созданный сайт должен быть доступен по адресу http://localhost:8000.

Как я упоминал ранее, нам нужно внедрить скрипт блокировки рендеринга во все наши сгенерированные страницы, для этого мы создадим файл gatsby-ssr.js и с помощью функции onRenderBody разместим скрипт в шапке с параметром setHeadComponents:

Скрипт позаботится о чтении пользовательских настроек темного режима: сначала он проверит, сохранены ли настройки пользователя в localStorage.

preferredTheme = localStorage.getItem('color-theme');

Затем он запрашивает ОС с помощью prefers-color-scheme CSS media query. Теперь мы можем установить переменную window.__theme с областью действия окна на найденное значение темы (к которому позже будет доступ из нашего компонента) и при необходимости поместить темный класс в наш HTML-элемент.

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

CSS-переменные

На этом этапе наш HTML-тег может иметь или не иметь темный класс, и мы можем использовать его для переключения цветов из селектора :root с помощью CSS-переменных. Для этого в нашем файле CSS нам нужно объявить цвета в виде переменных, как для светлой, так и для темной темы:

Например, вы определяете белый цвет фона, но если элемент :root (HTML-тег) получил класс dark, фон будет черным.

Затем во всем вашем CSS вместо обычного объявления цветов вы ссылаетесь на переменную CSS:

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

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

Имейте в виду, что вам нужно будет «дублировать» все объявления var в светлом и темном режиме для каждого свойства, которое необходимо изменить в зависимости от темы, в основном вам может понадобиться только цвет фона и текста, но вы можете пойти дальше с границами, тени, акцентные цвета и так далее.

Переключение темы

На данный момент наш веб-сайт темный (или светлый) в зависимости от предпочтений ОС, но мы хотим, чтобы пользователь мог менять тему во время навигации.

Для этого мы закодируем «Переключатель» (это может быть кнопка, ссылка, изображение или то, что вы используете или вписываете на свой сайт), который может отображаться на панели навигации или на странице настроек.

Наш базовый переключатель может работать только при доступе к окну (используется в браузере), Gatsby не может ссылаться на окно при рендеринге на стороне сервера, поэтому первое, что нам нужно, это проверить, можем ли мы получить доступ к окно, чтобы установить переменную WebsiteTheme, которая будет передана в состояние theme. Состояние theme используется вместе с компонентом для отображения правой кнопки. Нажатая кнопка запускает оконную функцию __setPreferredTheme, нашу основную функцию, которая обновляет тему в заголовке и сохраняет настройки темы в localStorage. Обновление темы изменит класс в HTML, что приведет к обновлению переменной CSS и немедленному переключению на выбранную тему.

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

Что дальше

Этот пример можно значительно улучшить, например, сценарий заголовка можно дополнительно оптимизировать и минимизировать (иначе он будет внедрен как есть); предпочтение переключателя может иметь три состояния (темный, светлый, автоматический). Вы можете сохранить настройку в Context, а не размещать ее в заголовке (но имейте в виду, что при неправильной обработке может возникнуть мерцание). Вы можете расширить свой CSS, чтобы иметь полную темную/светлую тему или реализовать в рамках, таких как Bootstrap, Tailwind или Material.

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