Convert a colour between HEX, RGB and HSL and check its relative luminance for contrast work.
HEX and RGB describe the same thing — three 8-bit channels — so converting between them is pure notation. HSL is a cylindrical remapping of that cube: hue is the angle of the dominant channel, lightness is the midpoint of the brightest and darkest channel, and saturation is how far the colour sits from grey at that lightness. Relative luminance is the perceptual weighting defined by WCAG 2.1: each channel is linearised out of sRGB's gamma curve and then weighted 0.2126 / 0.7152 / 0.0722, because human vision is far more sensitive to green than to blue. That luminance is what contrast ratios are built from, which is why it decides whether white or black text is more legible on this colour.
Relative luminance (WCAG 2.1)
L = 0.2126·R_lin + 0.7152·G_lin + 0.0722·B_lin
Contrast ratio
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
HSL lightness
L = (max(R,G,B) + min(R,G,B)) / 2
HSL lightness is a geometric midpoint of the channel extremes and ignores how sensitive the eye is to each primary. Pure yellow and pure blue both sit at 50% lightness, yet yellow looks far brighter — that difference is what relative luminance captures.
WCAG 2.1 AA requires 4.5:1 for normal body text and 3:1 for large text (18pt, or 14pt bold). AAA raises those to 7:1 and 4.5:1.
Only for colours whose channel bytes are duplicated pairs. #abc expands to #aabbcc, so the shorthand can express just 4,096 of the 16.7 million sRGB colours.
An alpha component in an rgba() value is parsed but ignored, because luminance and contrast are only meaningful once the colour has been composited over a known background.