scalpel@labs: ~/glossary/relative-luminance.mdx6 sections

Relative Luminance: The Brightness Behind Contrast

Relative luminance is a colour's perceived brightness on a 0–1 scale (0 = black, 1 = white). WCAG computes it by linearising sRGB channels and weighting them 0.2126R + 0.7152G + 0.0722B, because the eye favours green over blue.

extension: Scalpel Colorupdated: 2026-08-14read_time: 2 min
less relative-luminance.mdx

Why it matters

Contrast is about brightness difference, and brightness is not the average of the RGB channels. Pure green text on black is perfectly readable, but pure blue text on black is nearly unreadable. Both are "one channel at full, two at zero." The difference is that the human eye is far more sensitive to green than to blue. Relative luminance captures that asymmetry, and it is the only honest way to measure whether text is dark enough against its background to be readable.

Without this weighting, you could follow a formula and still end up with text that fails for low-vision readers. Relative luminance is the foundation that makes the WCAG contrast ratio actually predictive.

How it works

The sRGB transfer function converts 8-bit colour channels (0 to 255) into a linear perceptual space. This is necessary because sRGB is not linear: doubling the 8-bit value from 127 to 254 does not double the perceived brightness. Once linearised, the three channels are summed with fixed weights.

The formula is:

if RsRGB ≤ 0.03928 then R = RsRGB/12.92 else R = ((RsRGB + 0.055)/1.055)^2.4
if GsRGB ≤ 0.03928 then G = GsRGB/12.92 else G = ((GsRGB + 0.055)/1.055)^2.4
if BsRGB ≤ 0.03928 then B = BsRGB/12.92 else B = ((BsRGB + 0.055)/1.055)^2.4

L = 0.2126 × R + 0.7152 × G + 0.0722 × B

The weights (0.2126 for red, 0.7152 for green, 0.0722 for blue) come from human vision biology. Your eye has more cone cells tuned to green wavelengths, which is why green dominates perceived brightness.

What does not matter

Relative luminance is not the same as HSL lightness. hsl(60 100% 50%) (yellow) and hsl(240 100% 50%) (blue) both have 50% lightness, but yellow has a relative luminance of 0.93 whilst blue has 0.066. That is a forty-fold difference in perceived brightness. This is why HSL palettes can look uneven, and why WCAG uses relative luminance instead.

Also, relative luminance is asymmetric between sRGB color channels by design. It is not arbitrary, and changing the weights breaks everything downstream that depends on them (every contrast ratio, every WCAG conformance decision).

Code example

Computing relative luminance for #38bdf8 (a light cyan):

// 8-bit values from hex #38bdf8
const r8bit = 0x38; // 56
const g8bit = 0xbd; // 189
const b8bit = 0xf8; // 248

// Normalise to 0–1
const rsrgb = r8bit / 255; // 0.22
const gsrgb = g8bit / 255; // 0.74
const bsrgb = b8bit / 255; // 0.97

// Apply sRGB transfer function (simplified for values > 0.03928)
const r = Math.pow((rsrgb + 0.055) / 1.055, 2.4); // 0.034
const g = Math.pow((gsrgb + 0.055) / 1.055, 2.4); // 0.514
const b = Math.pow((bsrgb + 0.055) / 1.055, 2.4); // 0.942

// Weighted sum
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b; // 0.72

This light cyan has a luminance of approximately 0.72. On white (luminance 1.0), it yields a contrast ratio of (1.0 + 0.05) / (0.72 + 0.05) = 1.38:1, which fails even AA.

How Scalpel Color shows it

Relative luminance underlies every ratio in the Contrast tab. When you check two colours, Scalpel calculates their relative luminances, computes the contrast ratio from them, and displays whether the pair passes AA or AAA. Each colour swatch shows its luminance value on hover.


See wcag-contrast-ratio for how two luminances become a readability verdict, wcag-conformance-levels for what AA and AAA actually require, and oklch-color for a perceptual space that fixes luminance unevenness in palettes.

Sources