Documents v0.9.0 · previews run the real runtime · experimental features are marked exp

Theme switcher

One keyword state cycles through three themes, and the page colors and the button label follow it.

Live previewreal runtime

Click the Theme button several times.

How it works

  • state()line 2Makes each matching element the owner of an independent state with an initial value.
  • cycle()line 4Moves a state to the next value in a list, wrapping around. In an :on() rule it is the mutation --mode: cycle(light, dark).
  • :when()lines 6, 7Matches elements for which the condition is true, with states resolved from that element.
  • contentline 10On elements, a content value that reads state also becomes the element’s DOM text: a real text node, never HTML. The native declaration is kept as written.

A keyword state with more than two values. cycle() moves to the next keyword and wraps at the end; :when() rules pick the colors, and content writes the theme’s name into the button.

Native CSS alternative

prefers-color-scheme follows the system setting, and color-scheme with light-dark() picks colors from it. CSS alone cannot let the reader choose a theme on the page.

Limitations

  • The choice is not kept after a reload. Add persist("theme") to the state for that; it cannot store anything inside this sandboxed preview.

Implementation

2 files · 10 lines
style.cssreactive
/* ---- Reactive CSS -------------------------------------------------------------------------- */.themes { --theme: state(light); }.themes .switch:on(click) { --theme: cycle(light, dark, sepia); }.themes:when(--theme == dark) { background: #1c1917; color: #f5f5f4; }.themes:when(--theme == sepia) { background: #f3e7d0; color: #3f2d1c; }/* The button names the current theme, as real DOM text. */.themes .name { content: var(--theme); }
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

Source: site/src/catalog/interfaces/theme-switcher/. style.css from its Reactive CSS divider; the layout above it and the shared api.css run but are not shown.

Related

Step wizard

Three steps with Back and Next buttons, a step list you can click, and aria-current on the current step.

experimentalstate():on()set():nth-var()--attr-*

Task list

Native checkboxes whose label fades when done, with a short animation when a task is checked or unchecked.

state()event():just-checkedwhen()

Pricing toggle

A billing switch changes the price and shows the annual saving, with role="switch" kept in sync.

experimentalstate()toggle()--attr-*when()content