Skip to content

Instantly share code, notes, and snippets.

@arielsalminen
Last active October 24, 2022 19:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arielsalminen/8511d5ae8afaf088fe44672b0bf1550c to your computer and use it in GitHub Desktop.
Save arielsalminen/8511d5ae8afaf088fe44672b0bf1550c to your computer and use it in GitHub Desktop.
getContrastRatio.js
/*
* Clamp util.
*/
const clamp = (val, min, max) => {
return Math.min(Math.max(val, min), max)
}
export default clamp
import hexToRgb from "./hexToRgb.js"
import parseRgb from "./parseRgb.js"
import isHex from "./isHex.js"
/*!
* Calculates the contrast ratio between two colors.
*
* @param {String} A RGB or HEX color value
* @param {String} A RGB or HEX color value
* @return {String} The contrast ratio
*/
const getContrastRatio = (textColor, backgroundColor) => {
// Always convert to RGB for calc
if (isHex(backgroundColor)) {
backgroundColor = hexToRgb(backgroundColor)
}
if (isHex(textColor)) {
textColor = hexToRgb(textColor)
}
// Convert RGB strings to arrays
const [backgroundRed, backgroundGreen, backgroundBlue] = parseRgb(backgroundColor)
const [textRed, textGreen, textBlue] = parseRgb(textColor)
// Finally return contrast ratio
return contrast([backgroundRed, backgroundGreen, backgroundBlue], [textRed, textGreen, textBlue])
}
/*
* Get luminance from R, G and B.
*/
const luminance = (r, g, b) => {
const a = [r, g, 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
}
/*
* Get contrast of two colors.
*/
const contrast = (rgb1, rgb2) => {
const lum1 = luminance(rgb1[0], rgb1[1], rgb1[2])
const lum2 = luminance(rgb2[0], rgb2[1], rgb2[2])
const brightest = Math.max(lum1, lum2)
const darkest = Math.min(lum1, lum2)
return (brightest + 0.05) / (darkest + 0.05)
}
export default getContrastRatio
/*!
* Convert HEX to RGB.
*
* @param {String} HEX color value
* @return {String} RGB color value
*/
const hexToRgb = hex => {
// 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)
const rgb = {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`
}
export default hexToRgb
/*
* Is HEX color
*/
const isHex = color => {
return color.slice(0, 1) === "#"
}
export default isHex
import clamp from "./clamp.js"
/*
* Parse RGB values.
*/
const parseRgb = color => {
return extractComponents(color).map(parseRgbComponent)
}
// Extract components utility
const extractComponents = color => {
const component = /-?\d+(\.\d+)?%?/g
return color.match(component)
}
// Parse RGB component utility
const parseRgbComponent = (component, i) => {
if (i < 3) {
if (component.indexOf("%") != -1) {
return Math.round((255 * clamp(parseInt(component, 10), 0, 100)) / 100)
} else {
return clamp(parseInt(component, 10), 0, 255)
}
} else {
return clamp(parseFloat(component), 0, 1)
}
}
export default parseRgb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment