Design tokens from JSON to CSS
For whoever maintains a small site or app: at the end every design decision is in one file, the CSS is generated from it, and a test fails when someone writes a colour by hand.
- Skill areas
- Based on
- Updated
- ·
Before you start
-
A stylesheet in which colours, spacing and fonts recur as raw values.
-
A script step that can generate a file and check it in the build.
-
A test runner that can read the stylesheets.
Steps
Put the decisions in one file, in tiers
The token file holds every decision: colours, fonts, sizes, spacing, radii, focus and motion. Primitive values sit in one tier, roles (text, surface, border, action) refer to them, and components refer to the roles. A component never uses a primitive directly.
Generate the custom properties and check for drift
A script compiles the file into custom properties and keeps the references as var() references, so the tiers stay visible in the browser's tools. The same script in check mode fails when the generated file differs from the source; the check is part of the build.
Forbid raw values outside the generated file
A test reads every stylesheet and fails when a colour is written as a value anywhere but the generated file, or when a custom property in use is undefined. The same test limits media queries to the tokens' breakpoints.
Declare the contrast pairs and test them
The file lists the pairs of text and background and the focus ring against its background, each with the ratio it must meet. A test computes the ratios and fails when a change makes a pair unreadable.
Let layers decide the order
The cascade layers are declared once: tokens, base, layout, components, utilities, overrides. A utility always beats a component and a component always beats the base, whatever the selectors look like, so the specificity race ends.
Vendor another system's tokens with provenance
When the look belongs to another product, its token file is copied verbatim, and next to it the source, the version and the commit are recorded, along with every deliberate deviation. The own file holds only references into it. Values change at the source and are vendored again.
When not to use this
-
A single page that will not be maintained: custom properties at the top of the stylesheet are enough.
-
The design system already ships as a package with its own tokens and checks: use it, do not copy it.
-
Nobody runs the check: the generated file drifts from its source within a week.
Where it comes from
This site is built this way: the tokens are references into the vendored tokens of the Hintapiste.fi design system, the custom properties are generated, and the tests check drift, raw colours, undefined properties and the contrast pairs on every build.