liveBook · Manning

Relative luminance

As explained in Math for Web Design

Relative luminance is a normalized measure of the perceived lightness of a color, computed from linearized red, green, and blue components and ranging from black at 0 to white at 1.

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

How Math for Web Design covers it

How deep it goes
Descends through sRGB normalization, piecewise gamma correction, weighted summation, contrast calculation, and JavaScript implementation.
Examples
Uses pure blue against white, a JavaScript contrast calculator, and a CSS text-and-background compliance exercise.
What you can do after
Apply it via JavaScript to compute luminance and contrast ratios from RGB or hexadecimal colors.
How it connects
Connects relative luminance to sRGB, gamma correction, contrast ratio, WCAG, and accessible color.

Also explained in

Compare how 2 books explain relative luminance →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Math for Web Design. The section links point to the parts of the book it draws on.