This library is a port of next-themes for Svelte. All credit goes to pacocoursey and all next-themes contributors.
An abstraction for themes in your Svelte app - works with any Svelte environment (SvelteKit, Vite, Webpack, etc.)
- ✅ Perfect dark mode in 2 lines of code
- ✅ System setting with prefers-color-scheme
- ✅ Themed browser UI with color-scheme
- ✅ No FOUC (Flash of Unstyled Content)
- ✅ Sync theme across tabs and windows
- ✅ Disable transition flash when changing themes
- ✅ Force pages to specific themes
- ✅ Class or data attribute selector
- ✅ Theme context
- ✅ Svelte 5 ready with modern runes syntax
- ✅ Universal - works with any Svelte setup
- ✅ SvelteKit dependency
Check out the Live Example to try it for yourself.
$ pnpm add svelte-themes
# or
$ npm install svelte-themes
# or
$ yarn add svelte-themes
Add SvelteTheme
to your app's root component. In SvelteKit, this would be your +layout.svelte
.
<!-- src/routes/+layout.svelte (SvelteKit) -->
<!-- or src/App.svelte (Vite + Svelte) -->
<script lang="ts">
import { SvelteTheme } from 'svelte-themes';
let { children } = $props();
</script>
<SvelteTheme>
{@render children()}
</SvelteTheme>
storageKey = 'theme'
: Key used to store theme setting in localStoragedefaultTheme = 'system'
: Default theme name. IfenableSystem
is false, the default theme islight
forcedTheme
: Forced theme name for the current page (does not modify saved theme settings)enableSystem = true
: Whether to switch betweendark
andlight
based onprefers-color-scheme
enableColorScheme = true
: Whether to indicate to browsers which color scheme is used (dark or light) for built-in UI like inputs and buttonsdisableTransitionOnChange = false
: Optionally disable all CSS transitions when switching themesthemes = ['light', 'dark']
: List of theme namesattribute = 'data-theme'
: HTML attribute modified based on the active theme- accepts
class
anddata-*
(meaning any data attribute,data-mode
,data-color
, etc.)
- accepts
value
: Optional mapping of theme name to attribute value- Example:
{ dark: 'dark-theme', light: 'light-theme' }
- Example:
colorScheme
: Optional mapping of theme name to color scheme value- Example:
{ 'custom-dark': 'dark', 'custom-light': 'light' }
- Example:
Use the useTheme()
hook to access and change the active theme.
<script lang="ts">
import { useTheme } from 'svelte-themes';
const theme = useTheme();
</script>
<select bind:value={theme.theme}>
{#each theme.themes as name (name)}
<option value={name}>{name}</option>
{/each}
</select>
<button onclick={() => (theme.theme = 'dark')}>Dark mode</button>
<button onclick={() => (theme.theme = 'light')}>Light mode</button>
theme
: Active theme nameresolvedTheme
: IfenableSystem
is true and the active theme is "system", this returns whether the system preference resolved to "dark" or "light". Otherwise, identical totheme
systemTheme
: IfenableSystem
is true, represents the System theme preference ("dark" or "light"), regardless what the active theme isthemes
: The list of themes passed toSvelteTheme
(with "system" appended, ifenableSystem
is true)
<script>
import { SvelteTheme } from 'svelte-themes';
let { children } = $props();
</script>
<SvelteTheme>
{@render children()}
</SvelteTheme>
<script>
import { SvelteTheme } from 'svelte-themes';
let { children } = $props()
</script>
<SvelteTheme
themes={['corporate', 'neon', 'vintage']}
value={{
corporate: 'theme-corporate',
neon: 'theme-neon-bright',
vintage: 'theme-retro'
}}
attribute="class"
>
{@render children()}
</SvelteTheme>
<script>
import { SvelteTheme } from 'svelte-themes';
let { children } = $props()
</script>
<SvelteTheme
themes={['light', 'dark', 'midnight', 'dawn']}
colorScheme={{
midnight: 'dark', // Maps to CSS color-scheme: dark
dawn: 'light' // Maps to CSS color-scheme: light
}}
>
{@render children()}
</SvelteTheme>