Fastry использует трёхпозиционную систему цветовых режимов — Системный / Светлый / Тёмный — вместо бинарного переключателя. В этом посте объясняется, как она работает, как предотвращает мерцание и как её настроить.
Как это работает
Система состоит из трёх взаимодействующих частей:
- Атрибуты на
<html>— SSR-запасной вариант для посетителей с отключённым JavaScript - Скрипт начальной загрузки — выполняется до отрисовки страницы и согласовывает все три значения из хранилища
- Переключатель в шапке — выпадающее меню для выбора режима
Элемент HTML
В src/layouts/BaseLayout.astro элемент <html> содержит:
<html lang="ru" class="scroll-smooth dark" data-theme="blue" data-theme-mode="system">
Три части состояния взаимодействуют:
class="dark"— SSR-запасной вариант для посетителей с отключённым JS. Вариант тёмной темы Tailwind привязан к нему.data-theme-mode="system"— отражает сохранённый выбор пользователя и управляет иконкой в шапке.data-theme="blue"— палитра цветов по умолчанию.
Для посетителей с включённым JavaScript встроенный скрипт начальной загрузки в <head> выполняется до отрисовки body и согласовывает все три значения из хранилища.
Хранилище
localStorage.theme∈'system' | 'light' | 'dark'— сохранённый цветовой режим пользователя (по умолчанию'system')
В режиме 'system' начальная загрузка также подписывается на window.matchMedia('(prefers-color-scheme: dark)') и применяется при каждом изменении ОС.
Предотвращение мерцания (Flash of Wrong Theme)
Главная проблема цветовых режимов — мерцание неправильной темы, когда страница сначала отрисовывается в светлом режиме, а затем JS переключает на тёмный. Fastry решает это с помощью встроенного скрипта в <head>:
<script>
(function bootstrapColorMode() {
const theme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
// Применяем правильный класс ДО отрисовки body
// ...
})();
</script>
Этот скрипт работает синхронно перед любым рендерингом, поэтому пользователь всегда видит правильный цветовой режим с самого начала.
View Transitions
Система цветовых режимов полностью совместима с View Transitions API. При навигации между страницами выбранный режим сохраняется без сброса.
Настройка режима по умолчанию
Чтобы изменить режим по умолчанию для новых посетителей, отредактируйте атрибуты в src/layouts/BaseLayout.astro:
<!-- Светлый режим по умолчанию -->
<html lang="ru" class="scroll-smooth" data-theme-mode="light">
<!-- Тёмный режим по умолчанию -->
<html lang="ru" class="scroll-smooth dark" data-theme-mode="dark">
<!-- Системный по умолчанию (рекомендуется) -->
<html lang="ru" class="scroll-smooth dark" data-theme-mode="system">
Сохранённый выбор пользователя всегда имеет приоритет после выполнения начальной загрузки.
Компонент переключателя
Переключатель цветового режима находится в шапке в виде пилюли. Он показывает текущий режим и позволяет переключаться между тремя состояниями. Компонент находится в src/components/layout/ и использует только нативный JavaScript — никаких фреймворков.
Полная документация и исходный код доступны в репозитории Fastry.