Найти тему
Justice IT

Важность и реализация смены темы веб-приложений с использованием CSS-переменных

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

Почему темная тема так популярна?

Существует несколько причин, наиболее значимые из которых мы рассмотрим:

  1. В темное время суток темы с светлым текстом на темном фоне снижают нагрузку на глаза. Контраст между экраном устройства и окружающей средой становится менее заметным, что делает использование приложения более комфортным для пользователей. Кроме того, темная тема является важным средством доступности для людей с ограниченными возможностями здоровья.
  2. Исследования показывают, что большинство пользователей предпочитают темную тему из эстетических соображений. Однако для успешной реализации темной темы важно обеспечить минималистичный дизайн приложения, чтобы переключение темы не разрушало общее впечатление.
  3. Темная тема также актуальна для тех, кто хочет экономить заряд батареи своего смартфона. Исследования, проведенные разработчиками Android, показывают, что темная тема может сэкономить до 60% заряда батареи.

Что такое CSS-переменные?

CSS-переменные (пользовательские CSS-свойства) - это определенные автором CSS сущности, которые содержат конкретные значения и могут быть повторно использованы в документе. Они устанавливаются с использованием custom property нотации (например. --main-color: black;) и доступны через функцию var() (например. color: var(--main-color);) .

Более подробную информацию можно найти на MDN Web Docs.

Реализация

Для простоты работы мы будем использовать пакет node-sass в связке с React 18. Для этого инициализируем проект с помощью npm и добавим пакет node-sass:

npx create-react-app theme
npm i node-sass

После инициализации проекта очистим файловую структуру, оставив только файлы App.js и index.js в папке src.

Создадим файл стилей themes.scss в папке styles. В этом файле определим наши стили с помощью псевдоэлемента :root, чтобы все компоненты приложения могли использовать наши переменные:

// src/styles/themes.scss

:root {
--text-color: #121212;
--background: #FFFFFF;
}

Также создадим файл стилей для нашего App.js, чтобы проверить работу стилей:

// src/App.scss

body {
margin: 0;
padding: 0;
}

.App {
font-family: sans-serif;
text-align: center;
height: 100vh;
color: var(--text-color);
background-color: var(--background);
> div {
padding: 16px;
}
}

Не забудьте импортировать файл стилей в index.js:

// src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import '../src/styles/theme.scss';

ReactDOM.render(<App />, document.getElementById('root'));

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

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

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

Для этой задачи мы воспользуемся хуками React и localStorage.

Создадим файл ThemeProvider.js в папке providers, который будет отвечать за нашу тему:

// src/providers/ThemeProvider.js

import React, { createContext, useState, useEffect } from 'react';

export const ThemeContext = createContext({});

const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState(defineTheme);

useEffect(() => {
document.documentElement.dataset.theme = theme;
localStorage.setItem('theme', theme);
}, [theme]);

return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
};

export default ThemeProvider;

Мы создали контекст, через который будем передавать состояние темы вниз по дереву компонентов. С помощью хука useState мы будем хранить информацию о текущей теме. В useEffect мы будем обновлять тему в localStorage и в атрибуте тэга HTML при каждом изменении темы.

Теперь добавим кнопку переключения темы в компонент App.js:

// src/App.js

import React, { useContext } from 'react';
import ThemeSwitcher from './components/ThemeSwitcher/ThemeSwitcher';
import './App.scss';

function App() {
return (
<div className="App">
<h1>Welcome to My App</h1>
<p>Some content here...</p>
<ThemeSwitcher />
</div>
);
}

export default App;

Теперь создадим компонент ThemeSwitcher, который будет отвечать за переключение темы:

// src/components/ThemeSwitcher/ThemeSwitcher.js

import React, { useContext } from 'react';
import { ThemeContext } from '../../providers/ThemeProvider';

const ThemeSwitcher = () => {
const { theme, setTheme } = useContext(ThemeContext);

const toggleTheme = () => {
setTheme(theme === 'light' ? 'dark' : 'light');
};

return (
<button onClick={toggleTheme} style={{ padding: 12, fontWeight: 500 }}>
Switch Theme
</button>
);
};

export default ThemeSwitcher;

Теперь, при нажатии на кнопку, мы будем переключать атрибут у тега HTML. Однако стили пока не изменятся, поэтому дополним файл themes.scss и внесем изменения в уже существующий файл стилей App.scss:

// src/styles/themes.scss

:root[data-theme='light'] {
--text-color: #121212;
--background: #FFFFFF;
}

:root[data-theme='dark'] {
--text-color: #FFFFFF;
--background: #121212;
}

Теперь, при переключении темы, стили нашего приложения должны меняться соответствующим образом.

Заключение

Необходимо помнить, что не все инструменты являются универсальными, и у CSS-переменных тоже есть свои ограничения. Одно из них - работа с прозрачностью. CSS-переменные не поддерживают функции SCSS, такие как darken или lighten. Также следует учитывать, что добавление индивидуальных стилей для каждого компонента может усложнить описание стилей.

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