Vanilla JavaScript Projects

Project 60, Website sections

Theme Switcher

Let people choose light, dark or follow their system, pick an accent colour, and never see a white flash when the page loads.

Main API
matchMedia
Styling
CSS variables
Dependencies
None
Your browser
Checking

Try the themes

Pick light, dark or system and an accent colour. The preview card updates. Your choice is saved for next time.

Theme

Accent colour

Put this in the head, before your CSS, to stop the flash:

<script>
const t = localStorage.getItem("theme") || "system";
const dark = t === "dark" || (t === "system" &&
  matchMedia("(prefers-color-scheme: dark)").matches);
document.documentElement.dataset.theme = dark ? "dark" : "light";
</script>
Monthly salesSeptember
Revenue$48.2k
Orders1,284
Refunds0.8%

64% of the monthly goal reached.

How it works

  1. Colours are variablesEvery colour is a CSS variable. Dark mode just swaps the values, so no element needs its own dark rule.
  2. Three choices, one ruleLight and dark are fixed. System follows prefers-color-scheme and updates live when the operating system changes.
  3. Decide before paintA tiny script in the head sets the theme before the CSS loads, so there is no white flash on reload.
const mq = matchMedia("(prefers-color-scheme: dark)");
function apply(mode) {
  const dark = mode === "dark" || (mode === "system" && mq.matches);
  document.documentElement.dataset.theme = dark ? "dark" : "light";
  localStorage.setItem("theme", mode);
}
mq.addEventListener("change", () => apply(localStorage.getItem("theme") || "system"));

/* CSS */
:root { --bg: #fff; --ink: #111; }
[data-theme="dark"] { --bg: #111; --ink: #eee; }