Skip to content

Instantly share code, notes, and snippets.

@wgminer
Last active February 12, 2025 00:20
Show Gist options
  • Save wgminer/abe717c4b90e38d1e6f4 to your computer and use it in GitHub Desktop.
Save wgminer/abe717c4b90e38d1e6f4 to your computer and use it in GitHub Desktop.
A simple JavaScript function that takes two hex color values and calculates their contrast ratio (according to the WCAG 2.0 guidelines).
var contrast = function (foreground, background) {
var hexToRgb = function (hex) {
// Expand shorthand form (e.g. '03F') to full form (e.g. '0033FF')
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
// Returns {r: '', g: '', b: ''}
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
var luminance = function (rgbColor) {
var a = [rgbColor.r, rgbColor.g, rgbColor.b].map(function(v) {
v /= 255;
return (v <= 0.03928) ?
v / 12.92 :
Math.pow( ((v+0.055)/1.055), 2.4 );
});
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
}
var rgb1 = hexToRgb(foreground);
var rgb2 = hexToRgb(background);
var lum1 = luminance(rgb1);
var lum2 = luminance(rgb2);
var ratio = (Math.max(lum1, lum2) + 0.05)/(Math.min(lum1, lum2) + 0.05);
return (Math.round(ratio*100)/100) + ':1';
}
console.log(contrast('#000000', '#ffffff')); // 21:1
@SpeederX
Copy link

TS version, had to make some modification to the hexToRgb which was going null and set false instead

const contrast = function (foreground: string, background: string) {
    const hexToRgb = function (hex: string): {r: number; g: number; b: number} | false {
        // Expand shorthand form (e.g. '03F') to full form (e.g. '0033FF')
        const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;

        hex = hex.replace(shorthandRegex, function (m, r, g, b) {
            return r + r + g + g + b + b;
        });

        const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);

        return result
            ? {
                  r: parseInt(result[1], 16),
                  g: parseInt(result[2], 16),
                  b: parseInt(result[3], 16),
              }
            : false;
    };

    const luminance = function (rgbColor: {r: number; g: number; b: number}): number {
        const a = [rgbColor.r, rgbColor.g, rgbColor.b].map(function (v) {
            v /= 255;
            return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
        });
        return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
    };

    const rgb1 = hexToRgb(foreground);
    const rgb2 = hexToRgb(background);
    if (rgb1 && rgb2) {
        const lum1 = luminance(rgb1);
        const lum2 = luminance(rgb2);
        const ratio = (Math.max(lum1, lum2) + 0.05) / (Math.min(lum1, lum2) + 0.05);

        return Math.round(ratio * 100) / 100 + ":1";
    } else {
        return false;
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment