Relative luminance measures a color’s perceived brightness on a normalized scale from 0 for black to 1 for white. It supplies the lightness values used by the WCAG contrast-ratio formula, so frontend color choices can be checked numerically rather than judged by appearance alone. section 7.4.2 section 7.4.3
Calculate relative luminance from sRGB values in four steps:
- Normalize red, green, and blue by dividing each 0–255 channel value by 255. section 7.4.3
- Linearize each normalized channel: use c / 12.92 when c ≤ 0.04045; otherwise use ((c + 0.055) / 1.055)²·⁴. section 7.4.3
- Combine the linear channels with L = 0.2126Rₗ + 0.7152Gₗ + 0.0722Bₗ. The weights reflect greater visual sensitivity to green and lower sensitivity to blue. section 7.4.3
- Place the lighter luminance L₁ and darker luminance L₂ into CR = (L₁ + 0.05) / (L₂ + 0.05) to evaluate contrast. section 7.4.2
Pure blue text on white
Pure blue (#0000FF) becomes linear RGB (0, 0, 1), producing L = 0.0722. Against white at L = 1, the contrast ratio is (1 + 0.05) / (0.0722 + 0.05) = 8.59:1, exceeding the WCAG AAA threshold. The ratio is unchanged if the colors swap foreground and background roles. section 7.4.3 section 7.4.2
Listing 7.10 JavaScript code to calculate a contrast ratio
function hexToRgb(hex) { #1
hex = hex.replace(/^#/, ""); #2
if (hex.length === 3) { #3
hex = hex.split("").map(ch => ch + ch).join(""); #3
} #3
const num = parseInt(hex, 16);
return {
r: (num >> 16) & 255, #4
g: (num >> 8) & 255, #4
b: num & 255 #4
};
}
function relativeLuminance(r, g, b) { #5
let R_n = r / 255, G_n = g / 255, B_n = b / 255; #6
const toLinear = (c) => #7
c <= 0.04045 ? #7
c / 12.92 : #7
((c + 0.055) / 1.055) ** 2.4; #7
const R_l = toLinear(R_n); #7
const G_l = toLinear(G_n); #7
const B_l = toLinear(B_n); #7
return 0.2126 * R_l + 0.7152 * G_l + 0.0722 * B_l; #8
}
function getContrastRatio(color1, color2) { #9
const rgb1 = hexToRgb(color1);
const rgb2 = hexToRgb(color2);
const L1 = relativeLuminance(rgb1.r, rgb1.g, rgb1.b);
const L2 = relativeLuminance(rgb2.r, rgb2.g, rgb2.b);
const lighter = Math.max(L1, L2); #10
const darker = Math.min(L1, L2); #10
const ratio = (lighter + 0.05) / (darker + 0.05); #11
return ratio;
}
function checkCompliance(cr, isLargeText = false) { #12
const thresholds = {
aa: { normal: 4.5, large: 3.0 }, #13
aaa: { normal: 7.0, large: 4.5 } #13
};
const textType = isLargeText ? 'large' : 'normal';
return {
aa: cr >= thresholds.aa[textType], #14
aaa: cr >= thresholds.aaa[textType] #15
};
}
A JavaScript implementation converts three- or six-digit hex colors to RGB, linearizes each channel, and returns the weighted luminance; related functions calculate contrast and check WCAG compliance. section 7.4.4

