Last active
October 20, 2023 10:33
-
-
Save hellais/0e57c0fb7f445b3aea9e0443ce5396e8 to your computer and use it in GitHub Desktop.
Dark or Light color picker based on luminace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gray0 (#f8f9fa): #000000 | |
gray1 (#f1f3f5): #000000 | |
gray2 (#e9ecef): #000000 | |
gray3 (#dee2e6): #000000 | |
gray4 (#ced4da): #000000 | |
gray5 (#adb5bd): #000000 | |
gray6 (#868e96): #000000 | |
gray7 (#495057): #ffffff | |
gray8 (#343a40): #ffffff | |
gray9 (#212529): #ffffff | |
blue0 (#e7f5ff): #000000 | |
blue1 (#c9e8ff): #000000 | |
blue2 (#8dd5f8): #000000 | |
blue3 (#5db8fe): #000000 | |
blue4 (#37a6ed): #000000 | |
blue5 (#0588cb): #000000 | |
blue6 (#0f77b8): #ffffff | |
blue7 (#056aa6): #ffffff | |
blue8 (#005f9c): #ffffff | |
blue9 (#005a99): #ffffff | |
indigo0 (#edf2ff): #000000 | |
indigo1 (#dbe4ff): #000000 | |
indigo2 (#bac8ff): #000000 | |
indigo3 (#91a7ff): #000000 | |
indigo4 (#748ffc): #000000 | |
indigo5 (#5c7cfa): #000000 | |
indigo6 (#4c6ef5): #000000 | |
indigo7 (#4263eb): #ffffff | |
indigo8 (#3b5bdb): #ffffff | |
indigo9 (#364fc7): #ffffff | |
violet0 (#f3f0ff): #000000 | |
violet1 (#e5dbff): #000000 | |
violet2 (#d0bfff): #000000 | |
violet3 (#b197fc): #000000 | |
violet4 (#9775fa): #000000 | |
violet5 (#845ef7): #000000 | |
violet6 (#7950f2): #ffffff | |
violet7 (#7048e8): #ffffff | |
violet8 (#6741d9): #ffffff | |
violet9 (#5f3dc4): #ffffff | |
fuchsia0 (#f8f0fc): #000000 | |
fuchsia1 (#f3d9fa): #000000 | |
fuchsia2 (#eebefa): #000000 | |
fuchsia3 (#e599f7): #000000 | |
fuchsia4 (#da77f2): #000000 | |
fuchsia5 (#cc5de8): #000000 | |
fuchsia6 (#be4bdb): #000000 | |
fuchsia7 (#ae3ec9): #ffffff | |
fuchsia8 (#9c36b5): #ffffff | |
fuchsia9 (#862e9c): #ffffff | |
pink0 (#fff0f6): #000000 | |
pink1 (#ffdeeb): #000000 | |
pink2 (#fcc2d7): #000000 | |
pink3 (#faa2c1): #000000 | |
pink4 (#f783ac): #000000 | |
pink5 (#f06595): #000000 | |
pink6 (#e64980): #000000 | |
pink7 (#d6336c): #000000 | |
pink8 (#c2255c): #ffffff | |
pink9 (#a61e4d): #ffffff | |
red0 (#fff5f5): #000000 | |
red1 (#ffe3e3): #000000 | |
red2 (#ffc9c9): #000000 | |
red3 (#ffa8a8): #000000 | |
red4 (#ff8787): #000000 | |
red5 (#ff6b6b): #000000 | |
red6 (#fa5252): #000000 | |
red7 (#f03e3e): #000000 | |
red8 (#e03131): #000000 | |
red9 (#c92a2a): #ffffff | |
orange0 (#fff4e6): #000000 | |
orange1 (#ffe8cc): #000000 | |
orange2 (#ffd8a8): #000000 | |
orange3 (#ffc078): #000000 | |
orange4 (#ffa94d): #000000 | |
orange5 (#ff922b): #000000 | |
orange6 (#fd7e14): #000000 | |
orange7 (#f76707): #000000 | |
orange8 (#e8590c): #000000 | |
orange9 (#d9480f): #000000 | |
yellow0 (#fff9db): #000000 | |
yellow1 (#fff3bf): #000000 | |
yellow2 (#ffec99): #000000 | |
yellow3 (#ffe066): #000000 | |
yellow4 (#ffd43b): #000000 | |
yellow5 (#fcc419): #000000 | |
yellow6 (#fab005): #000000 | |
yellow7 (#f59f00): #000000 | |
yellow8 (#f08c00): #000000 | |
yellow9 (#e67700): #000000 | |
lime0 (#f4fce3): #000000 | |
lime1 (#e9fac8): #000000 | |
lime2 (#d8f5a2): #000000 | |
lime3 (#c0eb75): #000000 | |
lime4 (#a9e34b): #000000 | |
lime5 (#94d82d): #000000 | |
lime6 (#82c91e): #000000 | |
lime7 (#74b816): #000000 | |
lime8 (#66a80f): #000000 | |
lime9 (#5c940d): #000000 | |
green0 (#ebfbee): #000000 | |
green1 (#d3f9d8): #000000 | |
green2 (#b2f2bb): #000000 | |
green3 (#8ce99a): #000000 | |
green4 (#69db7c): #000000 | |
green5 (#51cf66): #000000 | |
green6 (#40c057): #000000 | |
green7 (#37b24d): #000000 | |
green8 (#2f9e44): #000000 | |
green9 (#2b8a3e): #000000 | |
teal0 (#e6fcf5): #000000 | |
teal1 (#c3fae8): #000000 | |
teal2 (#96f2d7): #000000 | |
teal3 (#63e6be): #000000 | |
teal4 (#38d9a9): #000000 | |
teal5 (#20c997): #000000 | |
teal6 (#12b886): #000000 | |
teal7 (#0ca678): #000000 | |
teal8 (#099268): #000000 | |
teal9 (#087f5b): #ffffff | |
cyan0 (#e3fafc): #000000 | |
cyan1 (#c5f6fa): #000000 | |
cyan2 (#99e9f2): #000000 | |
cyan3 (#66d9e8): #000000 | |
cyan4 (#3bc9db): #000000 | |
cyan5 (#22b8cf): #000000 | |
cyan6 (#15aabf): #000000 | |
cyan7 (#1098ad): #000000 | |
cyan8 (#0c8599): #000000 | |
cyan9 (#0b7285): #ffffff |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const hexToRGB = (hex) => { | |
/* Convert an RGB value (eg. #FFFFFF) into it's rgb triplet expressed as | |
* floating points. | |
* */ | |
// Strip the leading # from the hex code | |
hex = hex.replace(/^#?([0-9a-f]{6})$/i, '$1') | |
// Convert the hex into a number | |
hex = Number(`0x${hex}`) | |
// Simple bit shifting to slice off each component from the hex map | |
return { | |
r: parseFloat(hex >> 16 & 0xff) / 255.0, | |
g: parseFloat(hex >> 8 & 0xff) / 255.0, | |
b: parseFloat(hex & 0xff) / 255.0 | |
} | |
} | |
const sRGBTransform = (c) => { | |
/* Convert an sRGB to the correct color space in order to compute luminance formula. | |
* c is the color as float. | |
* */ | |
if (c <= 0.03928) { | |
return c/12.92 | |
} | |
return Math.pow(c+0.055/1.055, 2.4) | |
} | |
const getLuminance = ({r, g, b}) => { | |
/* | |
* Returns the luminance of an RGB triplet. Expects the r,g,b values to be | |
* already floating point numbers in the range of 0-1. | |
* */ | |
return 0.2126 * sRGBTransform(r) + 0.7152 * sRGBTransform(g) + 0.0722 * sRGBTransform(b) | |
} | |
const contrastRatio = (a, b) => { | |
/* | |
* Calculate contrast ratio as per WCAG 2.0 | |
* https://www.w3.org/TR/WCAG20-TECHS/G17.html | |
* the lighter color is l1, the darker is l2 | |
* | |
* a and b are luminance values for the two colors | |
* */ | |
l1 = b | |
l2 = a | |
if (a > b) { | |
l1 = a | |
l2 = b | |
} | |
return (l1 + 0.05) / (l2 + 0.05) | |
} | |
const pickTextColor = (color, darkColor, lightColor) => { | |
/* Returns the value of the prefered color between darkColor and lightColor | |
* to maximise the contrast against the color. | |
* Colors are expressed in thier RGB values as a hex string (eg. #FFCCDD). | |
* Returns the hex string of the chosen color between dark and light. | |
* */ | |
let darkLum = getLuminance(hexToRGB(darkColor)) | |
let lightLum = getLuminance(hexToRGB(lightColor)) | |
let colorLum = getLuminance(hexToRGB(color)) | |
const darkContrast = contrastRatio(colorLum, darkLum) | |
const lightContrast = contrastRatio(colorLum, lightLum) | |
if (contrastRatio(colorLum, darkLum) > contrastRatio(colorLum, lightLum)) { | |
return darkColor | |
} | |
return lightColor | |
} | |
let colors = { | |
white:"#ffffff", | |
black: "#000000", | |
ooniblue: "#0588cb", | |
gray1: "#f1f3f5", | |
violet5: "#845ef7", | |
lime9: "#5c940d", | |
cyan9: "#0b7285" | |
} | |
let whiteLum = getLuminance(hexToRGB(colors.white)) | |
let blackLum = getLuminance(hexToRGB(colors.black)) | |
let ooniblueLum = getLuminance(hexToRGB(colors.ooniblue)) | |
console.log(`Luminance of ${colors.white}: ${whiteLum}`) | |
console.log(`Luminance of ${colors.black}: ${blackLum}`) | |
console.log(`Luminance of ${colors.ooniblue}: ${ooniblueLum}`) | |
Object.keys(colors).forEach((name) => { | |
let chosen = pickTextColor(colors[name], colors.black, colors.white) | |
console.log(`${name} (${colors[name]}): ${chosen}`) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment