Hue Stability — Why Your Blue Drifts at the Edges
A blue palette should be blue. All twelve shades — from the lightest near-white to the deepest near-black.
In practice, the light shades lean slightly cyan or lavender. The dark shades lean indigo or violet. The middle shade — the brand blue — is the only one that reads as a pure blue.
This isn't a design mistake. It's the sRGB color space.
Why Hue Drifts
Blue in sRGB is defined by a specific primary: #0000ff. Every other blue is a mix of that primary with white, black, or other primaries.
When you lighten blue — add white — the mix becomes dominated by the RGB ratios near the white point. The blue primary in sRGB has a slightly cool, cyan-adjacent character at low saturation. Light blues drift toward cyan or lavender depending on the specific ratio.
When you darken blue — add black — the dark blue primary shifts toward indigo or violet.
The only shade that holds pure hue is the one at peak chroma — the shade with the highest saturation. That's the anchor. Everything above and below drifts away from it as chroma decreases.
A Concrete Example
Tailwind CSS blue palette, hue angle measured in CIELAB polar coordinates (LCH):
| Shade | Hex | Hue |
|---|---|---|
| blue-100 | #dbeafe | ~213° — cyan-blue |
| blue-300 | #93c5fd | ~217° |
| blue-500 | #3b82f6 | ~220° — pure blue |
| blue-700 | #1d4ed8 | ~225° |
| blue-900 | #1e3a8a | ~231° — blue-indigo |
From blue-100 to blue-900, the hue drifts ~18°. Each shade is individually recognizable as blue — but placed side by side, the progression reads as three different hues: cyan-blue, blue, blue-indigo.
How Stability Is Measured
The reference hue is the base shade — peak chroma, the truest blue.
For each swatch:
- Measure angular distance from the reference hue
- Compare against worst-case linear drift:
d_max(i) = 180° × (i / (N−1)) - Score = 1 − (RMSE of actual drift / RMSE of worst-case drift)
A score of 1.0 means no drift — every shade holds the reference hue exactly. A score below 0.85 means the drift is visible when shades are placed adjacent to each other.
Why It Matters for Design Systems
Hue drift creates a semantic inconsistency. The design intent is one blue. Components rendered at different lightness levels appear to use different colors.
- A light surface in the blue palette reads as sky blue
- The same component in a dark theme reads as indigo
- Placing them together on the same screen, the family identity is broken
Designers compensate by avoiding the drifted shades — narrowing the usable range of the palette — or by switching to a different blue that "works better" in dark contexts. Both paths add exceptions to the design system.
Working in LCH
Hue drift can be reduced by generating shades in LCH color space rather than sRGB. In LCH, hue (H) is an explicit coordinate that can be held constant while lightness (L) and chroma (C) vary independently.
The chromametry-generator constructs ramps in LCH, constraining hue to minimize drift. Hue stability then measures how well the generated output held the constraint.