๐จ CSS Theme Change
June 14, 2026 ยท View on GitHub
Tiny helper for CSS themes.
- One HTML attribute
data-set-themeto set theme theme. - Works with button, select, and checkbox
- Persists theme in localStorage
- Syncs all matching
data-set-themecontrols
Demo
Quick start
CDN
<script src="https://cdn.jsdelivr.net/npm/theme-change@latest/index.js"></script>
NPM
npm i theme-change@latest
import { themeChange } from "theme-change";
themeChange();
Use themeChange(false) when controls are mounted after initial page load.
Framework snippets
React
import { useEffect } from "react";
import { themeChange } from "theme-change";
useEffect(() => {
themeChange(false);
}, []);
Vue
import { onMounted } from "vue";
import { themeChange } from "theme-change";
export default {
setup() {
onMounted(() => {
themeChange(false);
});
},
};
Svelte
import { onMount } from "svelte";
import { themeChange } from "theme-change";
onMount(() => {
themeChange(false);
});
Astro
---
import { themeChange } from "theme-change";
---
<script>
themeChange(false);
</script>
CSS setup
Use daisyUI themes, or define your own theme tokens:
:root {
--my-color: #fff;
}
[data-theme="dark"] {
--my-color: #000;
}
[data-theme="pink"] {
--my-color: #ffabc8;
}
body {
background-color: var(--my-color);
}
HTML patterns
| Pattern | Preview | Minimal code |
|---|---|---|
| Button set | ![]() | <button data-set-theme="dark">Dark</button> |
| Button rotate | ![]() | <button data-set-theme="dark,light,pink">Rotate</button> |
| Select | ![]() | <select data-set-theme><option value="">Default</option><option value="dark">Dark</option></select> |
| Checkbox | ![]() | <input type="checkbox" value="dark" data-set-theme /> |
Notes:
- For checkbox: checked sets theme, unchecked clears theme.
- For rotate button: each click moves to the next item and loops.
- Controls with the same
data-keystay in sync.
Optional attributes
data-act-class
<button data-set-theme="" data-act-class="ACTIVE"></button>
<button data-set-theme="dark" data-act-class="ACTIVE"></button>
<button data-set-theme="pink" data-act-class="ACTIVE"></button>
data-act-attribute
Like data-act-class, but sets an arbitrary HTML attribute (instead of a class) on a button while its theme is active, and removes it when inactive. Useful for accessibility state such as aria-pressed or aria-current.
<!-- name:value โ active: aria-pressed="true", inactive: attribute removed -->
<button data-set-theme="dark" data-act-attribute="aria-pressed:true"></button>
<!-- bare name (no colon) โ boolean presence: active: aria-current="", inactive: removed -->
<button data-set-theme="pink" data-act-attribute="aria-current"></button>
Notes:
- Syntax is
name[:value]. Only the first colon splits name and value, so the value may itself contain colons (e.g.data-act-attribute="title:Active: dark"). - When inactive the attribute is fully removed (not set to a falsy value).
- Button-only, same as
data-act-classโ ignored on<select>and checkbox controls. - Can be combined with
data-act-classon the same element. - Also works with the legacy
data-toggle-themebuttons.
data-key
<select data-set-theme data-key="admin-panel"></select>
<button data-set-theme="dark" data-key="front-page"></button>
<input type="checkbox" value="pink" data-set-theme data-key="premium-user-theme" />
Backward compatibility
Legacy v2 attributes still work:
data-toggle-themedata-choose-theme



