A palette must encode which pairings are legal
Aliases: legal pairs · on-colour · palette constraints
What it is
Someone sets yellow-200 type on a yellow-400 fill because “both are yellow, they harmonise”. That pair should not exist on the palette. A palette is not only a column of colours you may pick. It has to encode which foregrounds may stand on which backgrounds: legal pairs are named as roles (“type on primary”, “type on container”); illegal pairs have no name to fetch. Whether a pair is readable enough is judged on the accessibility side. Here the palette itself refuses to assemble an illegal pair.
Why it happens
Free picking explodes combinations onto every screen. Under local pressure to “harmonise”, people pick adjacent stops of one hue, or pale type on a pale brand fill. If the palette offers values but not pairings, the constraint arrives at review, which is too late. Making “type on / icon on” a role bound to the ground cuts n×n down to about n: each container carries its own foreground. Illegal pairs are then not warned about — they cannot be fetched.
Legality is palette structure, not a threshold copied into a comment. How thresholds are set, and how translucency composites, belong to contrast criteria. The palette’s job is to make the default path walk already-paired roles, and to make deviations explicit, named, reviewable exceptions.
Where it stops holding
- Illustration, data visualisation and user-generated skins will break the table in bulk. Those channels should not pretend to be container roles; give them an exit that is not bound by the pairing table, and mark the exit “body text not guaranteed”.
- Dark and light pairings cannot share one table; the same role points at different values in each theme.
- Palette-legal is not field-legal: a photo or a translucent stack can push the composite out of the legal zone. That has to be checked after paint, not only on the palette.
Applying it
- Every role used as a ground carries its foreground role. Components reference the pair, not two arbitrary hexes.
- Hide illegal pairs from the colour picker, or make them unselectable.
- Exceptions get a name (“marketing display numeral”) and a list of places they must not go — body text, small icons.
- How to check: sample a set of components, list the foreground/background pairs they actually use, and match them to the table. Anything not on the table is red. Prefer fixing the reference over minting a new token for that pair.