Skip to content

Instantly share code, notes, and snippets.

@iaman
Created April 15, 2019 21:52
Show Gist options
  • Save iaman/00284c8d385f8599dca12fb991fe2ba5 to your computer and use it in GitHub Desktop.
Save iaman/00284c8d385f8599dca12fb991fe2ba5 to your computer and use it in GitHub Desktop.
An importable library for dealing with HEX/RGB colors and getting contrast info
const VALID_HEX_CHARS = {
"0": true,
"1": true,
"2": true,
"3": true,
"4": true,
"5": true,
"6": true,
"7": true,
"8": true,
"9": true,
"A": true,
"B": true,
"C": true,
"D": true,
"E": true,
"F": true
}
const getRGBComponentLuminance = (component) => {
if (typeof component == "string") component = parseInt(component);
if (component < 0) component = 0;
else if (component > 255) component = 1;
else component = component / 255;
if (component <= 0.03928) return component / 12.92;
else return Math.pow((component + 0.055) / 1.055, 2.4);
}
const HEXComponentToRGB = (component) => {
if (component.length == 1) component = `${component}${component}`;
return parseInt(component, 16);
}
const RGBComponentToHEX = (component) => {
if (typeof component == "string") component = parseInt(component);
const tempHEX = component.toString(16);
return (tempHEX.length == 1) ? `0${tempHEX}` : tempHEX;
}
const relativeLuminance = (color) => {
if (validHEXColor(color)) color = parseRGBFromHEX(color);
const splitColor = splitRGB(color);
const redLuminance = getRGBComponentLuminance(splitColor[0]);
const greenLuminance = getRGBComponentLuminance(splitColor[1]);
const blueminance = getRGBComponentLuminance(splitColor[2]);
return 0.2126 * redLuminance + 0.7152 * greenLuminance + 0.0722 * blueminance;
}
const splitHEX = (color) => {
if (color.length == 4) return color.replace("#","").split("");
else return color.replace("#","").match(/.{1,2}/g);
}
const splitRGB = (color) => {
return color.replace("rgb(","").replace("rgba(","").replace(")","").split(",");
}
export var validHEXColor = (color) => {
let valid = false;
if (typeof color == "string") {
const splitColor = color.split("");
const length = splitColor.length;
const includesHEX = splitColor[0] == "#";
if (includesHEX ? (length == 4 || length == 7) : (length == 3 || length == 6)) {
let i = includesHEX ? 1 : 0;
while (i < length) {
if (typeof VALID_HEX_CHARS[splitColor[i].toUpperCase()] == "undefined") break;
i++;
}
valid = (i == length && length != 0);
}
}
return valid;
};
export var validRGBColor = (color) => {
let valid = false;
if (typeof color == "string") {
const splitColor = splitRGB(color);
const length = splitColor.length;
if (length == 3 || length == 4) {
let i = 0;
while (i < length) {
if (isNaN((i == 3) ? parseFloat(splitColor[3]) : parseInt(splitColor[i]))) break;
i++;
}
valid = (i == length);
}
}
return valid;
}
export var parseHEXFromRGB = (color) => {
let HEX = "#";
const splitColor = splitRGB(color);
for (let i = 0; i < 3; i++) {
HEX += RGBComponentToHEX(splitColor[i]);
}
if (validHEXColor(HEX)) return HEX;
}
export var parseRGBFromHEX = (color) => {
let RGB = "";
const splitColor = splitHEX(color);
for (let i = 0; i < 3; i++) {
RGB += HEXComponentToRGB(splitColor[i]);
if (i != 2) RGB += ", ";
}
return `rgb(${RGB})`;
}
export var getFullHEXColor = (color) => {
const splitColor = color.split("");
const length = splitColor.length;
const includesHEX = splitColor[0] == "#";
let fullHEXColor = "#";
let i = includesHEX ? 1 : 0;
while (i < length) {
fullHEXColor += splitColor[i];
if (includesHEX && (length == 3 || length == 4)) fullHEXColor += splitColor[i];
i++;
}
return fullHEXColor;
}
const getContrastRatio = (background, foreground) => {
const l1 = relativeLuminance(background) + 0.05;
const l2 = relativeLuminance(foreground) + 0.05;
if (l1 > l2) return l1 / l2;
else return l2 / l1;
}
export var contrastRatio = (background, foreground) => {
return getContrastRatio(background, foreground).toFixed(2);
}
export var passesWCAGAA = (background, foreground) => {
const contrastRatio = getContrastRatio(background, foreground);
return {
normal: contrastRatio >= 4.5,
large: contrastRatio >= 3
}
}
export var passesWCAGAAA = (background, foreground) => {
const contrastRatio = getContrastRatio(background, foreground);
return {
normal: contrastRatio >= 7,
large: contrastRatio >= 4.5
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment