Привет, Хабр!
Публикуем вторую часть серии статей о создании современного блога на Nuxt.js. Сегодня реализуем темную тему в приложении, которое мы написали вместе с вами в первой части.
Обратите внимание, что код каждой части можно найти в собственной ветке на Github, а в

Темная тема — это цветовая схема любого интерфейса, которая отображает светлый текст и элементы интерфейса на темном фоне, что упрощает просмотр экрана на мобильных телефонах, планшетах и компьютерах при плохой освещенности. Темная тема уменьшает свет, излучаемый экраном, при сохранении минимального соотношения цветового контраста, необходимого для удобочитаемости.
Темная тема улучшает визуальную эргономику, снижая нагрузку на глаза, настраивая экран в соответствии с текущими условиями освещения и обеспечивая простоту использования в ноч��ое время или в темноте.
Также нельзя забывать о том, что использование темной темы в веб- и мобильных приложениях может продлить срок службы батареи устройства. Компания Google подтвердила, что темная тема на OLED экранах очень помогает продлить срок службы батареи.
Для реализации темной темы мы будем использовать модуль @nuxtjs/color-mode, который предоставляет следующие возможности:
Для начала установим модуль:
А затем добавим добавим информацию об этом модуле в секцию
Отлично! Теперь, если мы запустим наше приложение и откроем вкладку
На следующем этапе давайте реализуем переключатель, который будет менять темную тему на светлую и наоборот.
Если посмотреть на дизайн нашего приложения в Figma, то мы увидим, что рядом с переключателем темы также находится переключатель языка, который мы реализуем в одной из следующих статей этого цикла.
Сразу напишем компонент-обертку, который будет инкапсулировать эти переключатели и отвечать за внешние отступы до других компонентов.
Для этого создадим компонент
Компонент на Github.
Как мы видим, в этом компоненте нет никакой логики, он просто устанавливает внешние отступы для вложенных компонентов. Сейчас у нас только один вложенный компонент
Взглянем на секцию
Здесь мы реализуем метод
При изменении значения
Кроме того, здесь есть вычисляемое свойство
Шаблон компонента будет выглядеть следующим образом:
Здесь всё совсем просто! У нас есть кнопка, при клике на которую мы вызываем метод
Компонент на Github.
Остается только добавить этот компонент на главную страницу нашего приложения. После этого шаблон страницы должен выглядеть так:
Как вы, возможно, помните из первой части, для определения всех цветов в приложении мы использовали
Но проблема в том, что
Это ограничение можно обойти с помощью
Сейчас в нашем файле с переменными
Давайте для начала в этом же файле определим две цветовые схемы — светлую и темную — с помощью
Мы определили
О
Как мы видим, те цвета, которые раньше были прописаны напрямую в
Теперь наши
При переключении темы цветовая схема будет меняться в соответствии с заданными значениями и нам не нужно ничего менять в уже реа��изованных компонентах.
Благодаря этой статье мы научились реализовывать темную тему для приложения на Nuxt.js.
Удалось выполнить все шаги? Как вы думаете, темная тема — это просто хайп или все-таки необходимость? Делитесь мыслями в комментариях.
Ссылки на необходимые материалы:
Публикуем вторую часть серии статей о создании современного блога на Nuxt.js. Сегодня реализуем темную тему в приложении, которое мы написали вместе с вами в первой части.
Обратите внимание, что код каждой части можно найти в собственной ветке на Github, а в
master доступна версия приложения из последней опубликованной статьи.
Что такое темная тема?
Темная тема — это цветовая схема любого интерфейса, которая отображает светлый текст и элементы интерфейса на темном фоне, что упрощает просмотр экрана на мобильных телефонах, планшетах и компьютерах при плохой освещенности. Темная тема уменьшает свет, излучаемый экраном, при сохранении минимального соотношения цветового контраста, необходимого для удобочитаемости.
Темная тема улучшает визуальную эргономику, снижая нагрузку на глаза, настраивая экран в соответствии с текущими условиями освещения и обеспечивая простоту использования в ноч��ое время или в темноте.
Также нельзя забывать о том, что использование темной темы в веб- и мобильных приложениях может продлить срок службы батареи устройства. Компания Google подтвердила, что темная тема на OLED экранах очень помогает продлить срок службы батареи.
@nuxtjs/color-mode
Для реализации темной темы мы будем использовать модуль @nuxtjs/color-mode, который предоставляет следующие возможности:
- добавляет класс
.${color}-modeк тегу<html>для упрощения управлением темами CSS; - работает в любом режиме
Nuxt(static,ssrилиspa); - автоматически определяет цветовой режим системы на устройстве пользователя и может установить соответствующую тему, исходя из этих данных;
- позволяет синхронизировать выбранную тему между вкладками и окнами;
- позволяет использовать реализованные темы для отдельных страниц, а не для всего приложения (идеально подходит для постепенной разработки);
- также модуль поддерживает IE9+ (не уверен, что это всё еще актуально в современной разработке, но кому-то может пригодиться).
Для начала установим модуль:
npm i --save-dev @nuxtjs/color-modeА затем добавим добавим информацию об этом модуле в секцию
buildModules в файле nuxt.config.js:{
buildModules: [
'@nuxtjs/color-mode'
]
}Отлично! Теперь, если мы запустим наше приложение и откроем вкладку
Elements в консоли разработчика, то увидим, что к тегу html добавился класс, который соответствует теме операционный системы, например, в нашем случае class="light-mode".Переключатель темы
На следующем этапе давайте реализуем переключатель, который будет менять темную тему на светлую и наоборот.
Если посмотреть на дизайн нашего приложения в Figma, то мы увидим, что рядом с переключателем темы также находится переключатель языка, который мы реализуем в одной из следующих статей этого цикла.
Сразу напишем компонент-обертку, который будет инкапсулировать эти переключатели и отвечать за внешние отступы до других компонентов.
Для этого создадим компонент
AppOptions со следующим содержимым:<template lang="pug">
section.section
.content
.app-options
switcher-color-mode
</template>
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'AppOptions',
})
</script>
<style lang="scss" scoped>
.app-options {
display: flex;
margin-top: 24px;
}
</style>Компонент на Github.
Как мы видим, в этом компоненте нет никакой логики, он просто устанавливает внешние отступы для вложенных компонентов. Сейчас у нас только один вложенный компонент
switcher-color-mode, реализуем его.Взглянем на секцию
script этого компонента:<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'SwitcherColorMode',
computed: {
icon() {
return (this as any).$colorMode.value === 'light'
? 'assets/icons/sun.svg'
: 'assets/icons/moon.svg'
},
},
methods: {
changeColorMode() {
;(this as any).$colorMode.preference =
(this as any).$colorMode.value === 'light' ? 'dark' : 'light'
},
},
})
</script>Здесь мы реализуем метод
changeColorMode, который меняет тему в объекте, предоставляемом модулем @nuxtjs/color-mode.При изменении значения
$colorMode.preference также будет установлен соответствующий класс у тега html: class="light-mode" или class="dark-mode".Кроме того, здесь есть вычисляемое свойство
icon, которое возвращает нужную нам иконку в зависимости от выбранной темы. Обратите внимание, что для корректной работы нужно добавить иконки sun.svg и moon.svg в директорию assets/icons.Шаблон компонента будет выглядеть следующим образом:
<template lang="pug">
button(@click="changeColorMode")
img(
alt="theme-icon"
:src="getDynamicFile(icon)"
)
</template>Здесь всё совсем просто! У нас есть кнопка, при клике на которую мы вызываем метод
changeColorMode и меняем нашу тему. Внутри кнопки мы показываем изображение выбранной темы.Компонент на Github.
Остается только добавить этот компонент на главную страницу нашего приложения. После этого шаблон страницы должен выглядеть так:
<template lang="pug">
.page
section-header(
title="Nuxt blog"
subtitle="The best blog you can find on the global internet"
)
app-options
post-list
</template>Управление переменными
Как вы, возможно, помните из первой части, для определения всех цветов в приложении мы использовали
scss переменные, и теперь всё, что нам остаётся сделать, это изменять значения этих переменных в зависимости от выбранной темы.Но проблема в том, что
scss переменные задаются один раз при сборке приложения и в дальнейшем мы не можем переопределять их при изменении темы.Это ограничение можно обойти с помощью
js, но есть решение намного проще: мы можем использовать нативные css переменные.Сейчас в нашем файле с переменными
assets/styles/variables.scss секция с цветами выглядит следующим образом:// colors
$text-primary: rgb(22, 22, 23);
$text-secondary: rgb(110, 109, 122);
$line-color: rgb(231, 231, 233);
$background-color: rgb(243, 243, 244);
$html-background-color: rgb(255, 255, 255);Давайте для начала в этом же файле определим две цветовые схемы — светлую и темную — с помощью
css переменных::root {
// light theme
--text-primary: rgb(22, 22, 23);
--text-secondary: rgb(110, 109, 122);
--line-color: rgb(231, 231, 233);
--background-color: rgb(243, 243, 244);
--html-background-color: rgb(255, 255, 255);
// dark theme
&.dark-mode {
--text-primary: rgb(250, 250, 250);
--text-secondary: rgb(188, 187, 201);
--line-color: rgb(45, 55, 72);
--background-color: rgb(45, 55, 72);
--html-background-color: rgb(26, 32, 44);
}
}Мы определили
css переменные в селекторе :root. По стандарту css переменная задается и используется с помощью префикса --.О
css псевдоклассе :root можно прочесть на MDN и W3Schools. Цитата с MDN:css псевдокласс :root находит корневой элемент дерева документа. Применимо к HTML, :root находит тег html и идентичен селектору по тегу html, но его специфичность выше.Как мы видим, те цвета, которые раньше были прописаны напрямую в
scss переменные, сейчас указаны в css переменных как значения по умолчанию, а при наличии класса .dark-mode эти значения переопределяются.Теперь наши
scss переменные с цветами будут выглядеть следующим образом:$text-primary: var(--text-primary);
$text-secondary: var(--text-secondary);
$line-color: var(--line-color);
$background-color: var(--background-color);
$html-background-color: var(--html-background-color);При переключении темы цветовая схема будет меняться в соответствии с заданными значениями и нам не нужно ничего менять в уже реа��изованных компонентах.
Заключение
Благодаря этой статье мы научились реализовывать темную тему для приложения на Nuxt.js.
Удалось выполнить все шаги? Как вы думаете, темная тема — это просто хайп или все-таки необходимость? Делитесь мыслями в комментариях.
Ссылки на необходимые материалы:
