Skip to content
Work in progress - do not use in production. This component is still being built: it is not flagged Ready for Dev, so its markup, attributes, events and styles can all still change without notice, it is not covered by the accessibility gate, and it is not published to npm. It is on this site so the work can be seen and reviewed - nothing more.

ColorSchemeSwitcher

A control that toggles the document color scheme, rendered as <button is="root-color-scheme-switcher">.

Usage

<button is="root-color-scheme-switcher"><span aria-hidden="true">◐</span></button>

Where it starts, and what it remembers

Two modes, and no third. "System" is where the switch starts - on a reader who has never touched it - and not a state it can be left in: a control with three positions asks the reader to think about a machine setting, and the two that matter are the two they can see.

The order is markup, then the stored choice, then the system:

  • a mode attribute in the markup wins, and is not stored - it is the page's decision, not the reader's;
  • otherwise the choice the reader last made, from localStorage;
  • otherwise prefers-color-scheme.

The choice is stored under the key root:color-scheme. localStorage rather than sessionStorage because a color scheme is a preference, not the state of one reading session - and on a multi-page site every link followed is a fresh document that would otherwise open back on the system's scheme. A document that is not allowed to touch storage still honours the choice for as long as it is open.

Attributes

Attribute Type Default Description
mode 'light' | 'dark' the stored choice, else prefers-color-scheme Current scheme; reflected as the applied color-scheme

Events

Event Detail Description
root-color-scheme-switcher.change { mode } Fired when the mode changes

Extends

HTMLButtonElement - use with <button is="root-color-scheme-switcher">. Clicking toggles light and dark and writes color-scheme on the document root, so the light-dark() tokens re-theme the whole tree. The accessible name is managed via aria-label; keep the glyph aria-hidden.