Сохраняем тему и добавляем переключатель
В прошлой статье мы добавили поддержку тёмной темы на странице. Вот короткая версия:
- тёмная тема — это когда фон делают тёмным, а текст светлым, чтобы было удобно читать в темноте;
- браузеры умеют определять тёмную тему на устройстве и включать её на странице, если для этого на странице есть специальная настройка в CSS;
- вместо автоматического включения можно добавить ручной переключатель.
В прошлый раз мы проверили, как работает автопереключение, потом убрали его и добавили ручной режим. Сегодня объединим эти два подхода, а заодно научим браузер сохранять наши настройки.
Добавляем автопереключатель на страницу
Добавим автопереключение тёмной темы на страницу следующим способом:
- Мы оставляем ручной выбор темы на случай, если пользователь захочет сам выбрать, что ему удобнее.
- Ниже добавляем переключатель авторежима тёмной темы — когда он включён, используются системные настройки.
- После включения авторежима ручной выбор будет недоступен — мы его скроем с экрана.
- После выключения ручной выбор снова становится доступен.
Чтобы не городить с нуля элементы интерфейса, мы позаимствуем готовые компоненты из фреймворка Bootstrap 5. Оттуда нам нужен переключатель-слайдер. Мы вставим его в HTML-страницу после абзаца с ручным переключением. Сразу добавим вызов функции autoDarkLight() при нажатии на переключатель:
Настраиваем авторежим
Мы уже выяснили, что для автоматического включения тёмной темы достаточно добавить в стили такой медиазапрос:
Нам нужно добавить это в стили при включении авторежима и убрать оттуда при его выключении. Чтобы получить доступ к таблице стилей, добавим в самое начало скрипта dark.js такое:
// находим стили по тегу
const style = document.getElementsByTagName("style")[0];
// получаем доступ к разделу стилей
const styleSheet = style.sheet;
Теперь наша задача — написать функцию autoDarkLight() и добавить в неё всего одну проверку: нажат переключатель или нет. Если нажат — добавляем медиазапрос в стили, а если не нажат — убираем его оттуда.
Хитрость в том, что медиазапрос добавится в самый конец стилей, а значит, он применится самым последним. Получается, нам неважно, какие стили у страницы стояли до этого, — всё равно последним сработает наш автовыбор тёмной темы.
Сохраняем настройки
Страница теперь умеет переключаться в тёмный режим и автоматически, и вручную, но при перезагрузке всё слетает — все режимы нужно заново включать самому.
Чтобы сайт запоминал, что мы сделали в настройках, используем локальное хранилище браузера (оно же localStorage). Логика будет такая:
- При каждом переключении мы записываем в хранилище текущее значение переключателя. Если в памяти нет вообще никакого значения, значит, мы ещё не трогали этот переключатель.
- Когда страница загрузилась, мы достаём из памяти по очереди значение каждого переключателя и применяем их на страницу.
Применяем — это значит, что мы виртуально нажимаем на переключатели, если они активны. Это позволяет сразу установить всё в то положение, которое было до перезагрузки. Читайте комментарии, чтобы разобраться в логике работы с хранилищем:
Последнее, что нам осталось сделать, — сохранять в память текущее положение переключателей во время их изменения. Для этого добавим в самый конец функции darkLight () такую строку:
// сохраняем в памяти статус ручного переключателя
localStorage.setItem('selected',dark);
И то же самое сделаем в функции autoDarkLight () — добавим сохранение после установки видимости ручного переключателя:
localStorage.setItem('auto',true); ← если переключатель установлен;
localStorage.setItem('auto',false); ← если переключатель не установлен.
Результат
У нас получился красивый переключатель, который заставляет страницу слушаться системных настроек.
Также мы научились хранить состояние переключателей на устройстве.
Всё это живёт на нашей колхозной странице, на которую мы с каждым новым проектом добавляем всё больше элементов. Однажды она будет похожа на лавку торговца на турецком «Гранд базаре», а пока вот результат:
Посмотреть работу переключателей на странице проекта
Из интересного в этом проекте — симпатичный интерфейсный компонент в Bootstrap 5. В одной из будущих статей разберём, что там вообще интересного подвезли.
Готовый код смотрите в статье на сайте.