Theme colours belong to the content, not the stylesheet

When an editor picks a brand colour, half a dozen derived values have to stay legible. Here is how to derive them once instead of hard-coding them everywhere.

Avery Lin

Avery Lin

Content Architect ·

Abstract magenta gradient representing a derived colour palette

A colour picker in a CMS looks like a small feature. It is not. One hex value from an editor has to produce a legible accent, a surface tint, a hover state, a border and a glow — on light and dark backgrounds — without anyone checking each combination by hand.

Derive, do not enumerate

The temptation is to add fields: accent, accentHover, accentBorder, accentSurface. Now the editor owns five decisions instead of one, four of them are wrong, and none of them are checked for contrast. Take the seed colour and derive the rest, nudging toward the page background only far enough to stay readable.

Expose the results as custom properties on the block root. Hover and open states then work in class-land, which is where they are easiest to reason about, and a block that opts out falls back to the current text colour and simply renders neutral.

Watch the portals

Anything teleported out of the tree — dropdowns, calendars, dialogs — leaves the element that defined your custom properties behind. A variable that resolves to nothing paints transparent rather than falling back, so a select panel becomes an invisible rectangle over the page. Resolve those colours to concrete values before handing them to a portal.

Derived tokens are worth the arithmetic. They turn a support question — why is this text unreadable on our brand colour — into something the system simply cannot produce.

Design SystemsThemingAccessibility
Avery Lin

Written by

Avery Lin

Content Architect

Avery designs content models for teams moving off page-builder CMSes, and writes about keeping structured content structured.

Keep reading

All posts →