Dark mode
The dark: modifier, the class and media strategies, the persisted toggle and server rendering.
1 min readv1
The dark: modifier#
HTML
Switch the site theme to see this change.
<div nib="p=18px; bdrd=12px; bgc=#fff; cl=#0f172a; bd=1px solid #e2e8f0; dark:bgc=#0f172a; dark:cl=#e2e8f0; dark:bd=1px solid #1e293b">
Switch the site theme to see this change.
</div>Strategies#
| Output | Use when |
|---|---|---|
|
| users choose a theme |
|
| follow the OS, no toggle |
| nothing | the product has no dark theme |
The toggle (class strategy)#
runtime.toggleDarkMode() flips the dark class on <html>, returns the new state, stores it in
localStorage and follows the operating system until the user decides.
HTML
<button onclick="Nib.toggleDarkMode()">Theme</button>Avoiding a light flash on load (SSR)#
With server rendering the HTML arrives before any JavaScript. If the user chose dark, apply the class
before the first paint with a tiny inline script in <head>:
HTML
<script>
try {
const saved = localStorage.getItem("nib-dark");
const dark = saved !== null ? saved === "true" : matchMedia("(prefers-color-scheme: dark)").matches;
if (dark) document.documentElement.classList.add("dark");
} catch {}
</script>Designing both themes#
- Put paired colours in recipes (
card,input) so each surface declares its dark variant once. - Or use CSS variables: set
--surfacein:rootand.dark, and writebgc=var(--surface)everywhere. - Re-check contrast: muted text usually needs a lighter step in dark.