Привет, Хабр!
Публикуем вторую часть серии статей о создании современного блога на 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.
Удалось выполнить все шаги? Как вы думаете, темная тема — это просто хайп или все-таки необходимость? Делитесь мыслями в комментариях.
Ссылки на необходимые материалы:
- дизайн,
- Github,
- демо второй части.