Feature: Design tokens, with light and dark appearance
Description
The stylesheet is built from a documented set of design tokens covering typography, colour, spacing, border radius, borders, focus, controls, stacking, motion and layout width. Every one of them is a CSS custom property.
Every colour is declared once and carries both appearances, using the CSS
light- function:
:root {
color-scheme: light dark;
--theme-color-background: light-dark(#ffffff, #0f1319);
}
Appearance
The theme follows the appearance the visitor asked for. The operating system decides by default, and an explicit request on the root element overrules it in both directions:
<html data-theme="dark">
<html data-theme="light">
:root { color-scheme: light dark; }
:root[data-theme='light'] { color-scheme: light; }
:root[data-theme='dark'] { color-scheme: dark; }
That is the whole mechanism. It works because
light- resolves
against the used value of
color-, so switching one property
switches every colour. It does not work by influencing what
prefers- matches, which is tied to the operating system and
cannot be changed from CSS.
Setting
color- per appearance also makes form controls, scrollbars
and the canvas follow along.
No JavaScript ships with the extension - the attribute is there for whoever wants to build a switch.
Palettes
Four alternate palettes ship alongside the neutral default. A palette varies
accents only -
primary
,
secondary
, their hover states and the
focus ring - while neutrals, semantic colour, spacing, radius and typography
stay shared:
<html data-palette="ocean">
Available: ember, ocean, moss, violet. Omitting
the attribute selects the neutral default.
For a theme whose purpose is extension development, the palettes are a test surface rather than decoration: an extension that renders correctly across every palette in both appearances is one that is not hardcoding colour.
Re-theming without a build
Custom properties survive compilation, so a site package can re-theme the extension from its own CSS without rebuilding the SCSS:
:root {
--theme-color-primary: light-dark(#7b1fa2, #ce93d8);
--theme-font-family-sans: 'Mulish', system-ui, sans-serif;
}
Impact
The palette is deliberately neutral. This is a theme for extension development, and its job is to make document structure legible without biasing the design of the extension being built against it.
Every colour was checked for contrast against both the background and the
surface of its own appearance: body text clears 4.5:1 and any border that
delimits a control clears 3:1. Semantic colour carries three tokens per meaning
- the accent for text and borders,
-- for a foreground on
a solid fill, and
-- for the soft tint an alert sits
on - because one value cannot do all three jobs.
The design is flat. There are no elevation tokens, and the only shadow is
the focus ring, because a visible focus indicator is a requirement rather than
decoration. It is split into
-- and a composite
built around it, because
light- takes colours and not shadows.
Note
light- is supported by Firefox 120, Chrome and Edge 123, and
Safari 17.5 - Baseline since May 2024.
Note
The token names changed while this was still unreleased, which makes it a rename rather than a breaking change: no version had shipped at that point.
| Previously | Now |
|---|---|
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
-- …
-- |
-- …
-- |
The spacing scale is now a 5px grid - 5, 10, 15, 20, 25, 30, 40, 60 - rather than the doubling scale it replaced.