web-styling-theming
Runtime Theming Patterns
Quick Guide: A theme is decided by two independent signals -- the OS preference (
prefers-color-scheme) as the default and an explicit attribute on<html>as the override that wins in both directions. The attribute must be stamped by a synchronous inline script in<head>before first paint; anything running in an effect flashes on every load. Persist the preference (light | dark | system), never the resolved value, so "system" stays a live subscription to the OS. Themes swap token values under stable role names, one complete block per scope, withcolor-schemedeclared in each so native UI follows.next-themesautomates the script, the persistence, the live tracking, the attribute and the transition suppression -- but it cannot make server-rendered markup match, sotheme,resolvedThemeandsystemThemeareundefineduntil mount.
Detailed Resources:
- For code examples, see examples/ folder:
- core.md - Dual signal CSS, pre-paint boot script, SSR and cookie theming, three-state preference module,
next-themescontract, semantic token switching - advanced.md - Multi-brand axis, nested theme scopes, portal caveats, transition suppression, reduced motion, browser chrome
- core.md - Dual signal CSS, pre-paint boot script, SSR and cookie theming, three-state preference module,
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST stamp the theme attribute from a synchronous inline script in <head> before first paint - NEVER from useEffect, useLayoutEffect, or any code that runs after hydration)