В современных веб-приложениях часто требуется поддержка нескольких цветовых тем: светлой, тёмной или пользовательских вариантов. SvelteKit, благодаря своей реактивной архитектуре и интеграции с UI-библиотеками, позволяет реализовать динамическую смену тем с высокой производительностью и гибкостью.
Первым шагом является создание глобального состояния темы. В
SvelteKit для этого используется stores из пакета
svelte/store:
import { writable } from 'svelte/store';
export const theme = writable('light');
writable создаёт реактивное хранилище, которое позволяет
компонентам подписываться на изменения темы и автоматически обновлять
интерфейс при переключении.
Большинство UI-библиотек для SvelteKit (например, Svelte Material UI, Shadcn UI) предоставляют возможность передачи темы через пропсы или контекст. Рассмотрим пример с глобальной CSS-переменной:
<script>
import { theme } from './stores.js';
let currentTheme;
const unsubscribe = theme.subscribe(value => currentTheme = value);
$: document.documentElement.setAttribute('data-theme', currentTheme);
</script>
<button on:click={() => theme.set(currentTheme === 'light' ? 'dark' : 'light')}>
Сменить тему
</button>
<style>
:root[data-theme='light'] {
--background-color: #ffffff;
--text-color: #111111;
}
:root[data-theme='dark'] {
--background-color: #1e1e1e;
--text-color: #f0f0f0;
}
body {
background-color: var(--background-color);
color: var(--text-color);
}
</style>
В этом примере реактивность SvelteKit автоматически обновляет стили при смене значения темы. Все компоненты, использующие CSS-переменные, изменяют свои цвета без необходимости перерисовки или ручного обновления стилей.
UI-библиотеки для SvelteKit обычно предоставляют собственные механизмы темизации:
Svelte Material UI (SMUI) SMUI использует тему
через SMUITheme и CSS-переменные. Для динамической смены
темы можно подключить store к настройкам:
<SMUITheme theme={$theme}>
<Button>Пример кнопки</Button>
</SMUITheme>Shadcn UI для SvelteKit Shadcn UI применяет темы
через class на уровне корневого компонента или через
контекст. Для динамической смены темы достаточно менять класс на
<body> или контейнере приложения.
<div class={$theme}>
<Card>Контент карточки</Card>
</div>Чтобы пользовательский выбор темы сохранялся между сессиями, можно
использовать localStorage:
import { writable } from 'svelte/store';
const storedTheme = localStorage.getItem('theme') || 'light';
export const theme = writable(storedTheme);
theme.subscribe(value => {
localStorage.setItem('theme', value);
document.documentElement.setAttribute('data-theme', value);
});
Такой подход обеспечивает автоматическую загрузку последней выбранной темы при повторном открытии приложения.
Для улучшения UX рекомендуется добавить анимацию при смене темы:
body {
transition: background-color 0.3s ease, color 0.3s ease;
}
Переходы CSS обеспечивают плавное изменение фона и цвета текста без перерисовки компонентов.
Для расширения функциональности можно создать объект с набором доступных тем и их цветов:
export const themes = {
light: {
'--background-color': '#ffffff',
'--text-color': '#111111'
},
dark: {
'--background-color': '#1e1e1e',
'--text-color': '#f0f0f0'
},
ocean: {
'--background-color': '#2b3a42',
'--text-color': '#a6c8d1'
}
};
export function applyTheme(name) {
const selected = themes[name];
Object.entries(selected).forEach(([varName, value]) => {
document.documentElement.style.setProperty(varName, value);
});
}
Это позволяет добавлять новые темы без изменения компонентов и
UI-библиотеки, просто вызывая applyTheme('ocean').
SvelteKit позволяет связывать изменение темы с реактивными переменными в компонентах. Например, переключатель темы может автоматически менять внешний вид всех кнопок и карточек, если их стили зависят от CSS-переменных.
<Button style="background-color: var(--background-color); color: var(--text-color)">
Реактивная кнопка
</Button>
Использование CSS-переменных вместе с реактивными стором обеспечивает максимальную гибкость и производительность, минимизируя необходимость ручного контроля за каждым компонентом.
store для темы.localStorage.Такой подход обеспечивает централизованное управление внешним видом приложения и позволяет динамически менять тему без пересборки компонентов.