Practical guide

HSL Lightness Is Not Contrast: Compare Equal-Lightness Hues

HSL lightness describes a color coordinate, not its contrast against a reading surface. Equal-lightness yellow and blue can have very different sRGB relative luminance and white-background contrast.

Designers and developers applying color in CSS · 7 minute read · Published

Separate HSL lightness from relative luminance

Moving an HSL lightness slider is a convenient way to edit a color. It does not measure how that color compares with a particular background. CSS Color 4 describes HSL as non-uniform: equal changes in its coordinates do not create equal perceived changes across hues. [1]

For an in-range sRGB color, the CSS conversion code calculates HSL lightness from the largest and smallest encoded RGB components: (maximum + minimum) / 2. WCAG relative luminance instead uses linearized sRGB components with unequal weights. These quantities have different definitions and different jobs. [2] [3]

Use HSL to choose a color; use the actual supported foreground/background pair to calculate contrast. Do not turn “L is 50%” into a readability approval.

Compare yellow and blue with the same HSL lightness

The constructed colors hsl(60 100% 50%) and hsl(240 100% 50%) are opaque sRGB yellow and blue. Yellow has normalized RGB (1, 1, 0); blue has (0, 0, 1). Both have minimum 0, maximum 1 and HSL lightness 0.5.

For these endpoint components, the sRGB linearized values are also 0 or 1. Yellow therefore has relative luminance 0.2126 + 0.7152 = 0.9278; blue has 0.0722. They share HSL lightness while giving very different luminance. [3]

On a phone, scroll inside the table. Its region can be focused and moved with the arrow keys.

Constructed opaque sRGB hues at HSL lightness 50%
HueRGB bytesRelative luminanceAgainst whiteAgainst black
Yellow 60°255, 255, 00.92781.073839:119.556000:1
Blue 240°0, 0, 2550.07228.592471:12.444000:1
Red 0°255, 0, 00.21263.998477:15.252000:1
Green 120°0, 255, 00.71521.372190:115.304000:1

These ratios are original calculations for the stated opaque colors and surfaces. They are not measurements of anti-aliased letter edges or a certificate for an interface.

Use the correct conversion and pair formula

s = RGB_byte / 255
linear(s) = s / 12.92, if s <= 0.04045
linear(s) = ((s + 0.055) / 1.055) ** 2.4, otherwise
L = 0.2126 * linear(R) + 0.7152 * linear(G) + 0.0722 * linear(B)
ratio = (lighter_L + 0.05) / (darker_L + 0.05)

Apply the conversion to each normalized component before weighting it. Do not weight encoded bytes directly for arbitrary intermediate colors, and do not average the two colors’ HSL lightness values. Keep enough precision for the intended comparison; the table’s shortened output is a display choice. [3] [4]

Compare two opaque sRGB hues at lightness 50%

First color patch

Second color patch

Waiting for the bounded calculation.

Change the backdrop before drawing a conclusion

White has relative luminance 1; black has 0. Against white, yellow’s ratio is 1.05 / 0.9778, while blue’s is 1.05 / 0.1222. Against black, use (L + 0.05) / 0.05. The same color therefore answers a different contrast question when its adjacent surface changes. [4]

The demonstration lets you compare six exact pure hues at saturation 100% and lightness 50%, against explicitly opaque white or black. The labels stay outside the color patches. Its results come from the stated sRGB model; the returned browser color strings are reported separately from the calculations.

A photograph, gradient, transparent color, group opacity or wide-gamut value needs its actual model. The transparent-text guide covers its narrower single solid-backdrop case. Do not apply this opaque-hue calculation to those different conditions.

Choose color roles, then review the actual pairs

Start with the real task: paragraph text on the page surface, a label inside a panel, or another specific adjacent pair. Identify both CSS colors and the relevant state. Choose a hue or role, calculate its pair and revise that pair as needed. Changing HSL lightness may help, but the ratio has to be recalculated rather than assumed.

Keep font size, weight, meaningful state cues and actual rendering in the wider review. A color-ratio calculation does not establish all text or interaction requirements. If a palette generator makes six hues share one lightness coordinate, review every pair used in the interface rather than approving the collection as a whole.

The patch itself is a bounded comparison aid. The selected backdrop defines the calculation; it does not recolor the surrounding page. Read the named backdrop and ratio in the output instead of guessing from the page’s paper color.

Try two complete comparison cases

These are original teaching cases with explicit color and backdrop assumptions.

Case 1

Yellow and blue both use hsl(H 100% 50%). Must their contrast against white match?

Show answer and explanation for case 1

No. HSL lightness does not determine relative luminance.

The stated yellow has luminance 0.9278 and blue 0.0722. Against white their ratios are approximately 1.073839:1 and 8.592471:1. Compare actual RGB-derived luminance, not the shared HSL coordinate.

Case 2

Can the blue/white result be copied into a blue/black text review?

Show answer and explanation for case 2

No. The background is part of the pair.

Opaque blue against white gives about 8.592471:1, while the same blue against black gives 2.444:1. Recalculate with the specified adjacent background and retain the broader reading and interaction review.

Sources and further reading

  1. W3C CSS Color 4: HSLBounded syntax and non-uniformity explanation. Selected scopes consulted 9 November 2026; linked documents not all read.
  2. W3C CSS Color 4: RGB to HSL codeSupports (minimum + maximum)/2 for lightness. Selected scopes consulted 9 November 2026; linked documents not all read.
  3. W3C WCAG 2.2: relative luminanceComplete definition including the 0.04045 conversion and channel weights. Selected scopes consulted 9 November 2026; linked documents not all read.
  4. W3C WCAG 2.2: contrast ratioComplete definition, actual background context and anti-aliasing limitations. Selected scopes consulted 9 November 2026; linked documents not all read.