Skip to content

Distance Metrics ​

color_distance measures how different two colors are. The default metric, CIEDE2000 (ΔE00), is also used inside the palette and accessibility audits. The implementations are in src/color/metrics.ts.

Available metrics ​

metricSpaceSummary
deltaE2000 (default)CIE L*a*b* (D65)CIEDE2000, with lightness, chroma and hue weighting and the blue rotation term
deltaE94CIE L*a*b* (D65)CIE94, graphic-arts constants; not symmetric
deltaE76CIE L*a*b* (D65)Plain Euclidean distance in Lab
euclideansRGB 0–255Plain Euclidean distance in RGB
weightedsRGB 0–255RGB distance with each channel weighted by 0.3 / 0.59 / 0.11

Lab values come from the 8-bit sRGB color via XYZ with the D65 white point (X 95.047, Y 100, Z 108.883). color_distance has no other parameters; the weights and constants below are fixed.

Formulas ​

Euclidean (RGB) ​

text
d = √( ΔR² + ΔG² + ΔB² )          range 0 … 441.67 (black ↔ white)

Weighted (RGB) ​

text
d = √( (0.3·ΔR)² + (0.59·ΔG)² + (0.11·ΔB)² )

The weights are the classic luma coefficients: green differences count most and blue least. This is still an RGB metric, not a perceptual one.

ΔE 1976 ​

text
ΔE76 = √( ΔL*² + Δa*² + Δb*² )

ΔE 1994 ​

text
ΔE94 = √( (ΔL/S_L)² + (ΔC/S_C)² + (ΔH/S_H)² )
S_L = 1,  S_C = 1 + 0.045·C₁,  S_H = 1 + 0.015·C₁,  k_L = k_C = k_H = 1

C₁ is the chroma of the first color, so swapping color1 and color2 changes the result: #6750a4 → #7d5fc4 is 8.01, the reverse is 7.93.

ΔE 2000 ​

CIEDE2000 as formulated by Sharma, Wu & Dalal (2005), with k_L = k_C = k_H = 1:

text
ΔE00 = √( (ΔL'/S_L)² + (ΔC'/S_C)² + (ΔH'/S_H)² + R_T·(ΔC'/S_C)·(ΔH'/S_H) )

It adds an a* rescaling for near-neutral colors (G), lightness, chroma and hue weighting functions (S_L, S_C, S_H with the hue-dependent T term), and a rotation term R_T for the blue region. It is symmetric.

Verified

The implementation was run against the 34 test pairs published by Sharma, Wu & Dalal (2005). All 34 agree with the published ΔE00 values to 4 decimals.

Real comparisons ​

color_distance output for the same pairs under every metric:

PairdeltaE2000deltaE94deltaE76euclideanweighted
#6750a4 vs #7d5fc47.448.0111.4241.6311.59
#7d5fc4 vs #6750a47.447.9311.4241.6311.59
#808080 vs #8a8a8a3.663.893.8917.326.71
#0000ff vs #3c3cff7.688.7422.9784.8539.71
#ffff00 vs #c3c30013.8320.9527.2384.8539.71
#1f1f1f vs #1c1b1e2.762.882.885.102.53
json
{ "color1": "#0000ff", "color2": "#3c3cff", "metric": "deltaE2000" }
text
Distance between #0000ff and #3c3cff: 7.68

What the table shows:

  • RGB metrics can't tell these apart. The blue pair and the yellow pair are both 84.85 apart in RGB (and 39.71 weighted), but ΔE2000 rates the yellow pair almost twice as different (13.83 vs 7.68).
  • ΔE76 inflates differences between saturated colors. 22.97 for the blue pair against 7.68 in ΔE2000. CIEDE2000's chroma weighting, plus its blue-region rotation term, corrects for this.
  • For greys, ΔE94 = ΔE76. With zero chroma, both reduce to the lightness difference (3.89).
  • Only ΔE94 depends on argument order.

How the tools use ΔE2000 ​

WhereThreshold
check_palette_accessibilityindistinguishableThreshold, default 10 (1–30)
audit_design_md CVD collisionscvdThreshold, default 10 (1–30)
audit_design_md near-duplicate tokensbelow 2 (fixed)
audit_ui_colors swatch CVD collisionsbelow 8 (fixed)
fix_contrast, check_contrast fix suggestionpicks the candidate with the smallest ΔE2000 shift and reports it
generate_categorical_palettemaximizes the minimum ΔE2000 under normal vision and protanopia, deuteranopia, tritanopia
generate_palette_with_locksΔE2000 to the locked colors when choosing candidates

These thresholds are deliberately large: they ask whether two UI colors stay clearly distinct, not whether they are measurably different.

HCT distance (theme matching only) ​

The theme-matching tools do not use ΔE. They use their own weighted HCT distance, where tone counts twice (see Theme Matching). It is not available as a color_distance metric. It also behaves differently for near-greys: #1f1f1f vs #1c1b1e is 2.76 in ΔE2000, but about 47 in the HCT matcher, because their meaningless hues differ by 84°.

See Also ​

Released under the MIT License.