Last active
March 13, 2025 21:27
-
-
Save caseywatts/3b82dec0fda2dbf10454655700609cd2 to your computer and use it in GitHub Desktop.
Maryland Color Scale Generation
This file contains hidden or 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
// note: this is using OKLCH, see https://oklch.com/ | |
// https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl | |
import Color from "colorjs.io"; | |
let marylandRedBase = new Color("oklch(52.44% 0.2043 17)"); | |
let marylandAntiRedBase = new Color("oklch(52.44% 0.2043 197)"); | |
let marylandGoldBase = new Color("oklch(84.63% 0.1611 83.87)"); | |
let marylandAntiGoldBase = new Color("lch(65.14% 57.88 274.65)"); | |
let marylandBlueBase = new Color("oklch(68.06% 0.173 281.52)"); | |
let marylandCyanBase = new Color("oklch(66.13% 0.1182 227.75)"); | |
// USWDS shares out luminance values in the color grades table in relative luminance values, not OKLCH luminance values | |
// https://www.w3.org/WAI/GL/wiki/Relative_luminance | |
// https://designsystem.digital.gov/design-tokens/color/overview/#magic-number-2 | |
// We generated OKLCH luminance values by translating them out of the uswds blue scale colors on https://oklch.com/ | |
// Our generated luminance values weren't actually in the right ranges, but this was a helpful starting point | |
const blueLuminanceMapping = { | |
"05": 96.93, | |
10: 92.4, | |
20: 83.32, | |
30: 74.38, | |
40: 65.46, | |
50: 56.14, | |
60: 47.34, | |
70: 38.92, | |
80: 30.08, | |
90: 20.43, | |
}; | |
const redCoolVividLuminanceMapping = { | |
"05": 96.59, | |
10: 90.96, | |
20: 81.32, | |
30: 71.21, | |
40: 60.9, | |
50: 50.01, | |
60: 39.62, | |
70: 30.05, | |
80: 18.71, | |
90: 7.93, | |
}; | |
const yellowVividLuminanceMapping = { | |
"05": 96.4, | |
10: 91.77, | |
20: 84.75, | |
30: 72.83, | |
40: 60.63, | |
50: 50.51, | |
60: 42.06, | |
70: 31.91, | |
80: 20.64, | |
90: 7.65, | |
}; | |
const cyanLuminanceMapping = { | |
"05": 96.83, | |
10: 90.97, | |
20: 80.47, | |
30: 70.27, | |
40: 59.66, | |
50: 49.37, | |
60: 39.86, | |
70: 30.28, | |
80: 22.11, | |
90: 7.57, | |
}; | |
function scaleForBaseColor(baseColorName, baseColor, luminanceMapping) { | |
let baseColorOKLCH = baseColor.to("oklch"); | |
return Object.keys(luminanceMapping).map((grade) => { | |
const luminance = luminanceMapping[grade] / 100; | |
let newColor = new Color(baseColorOKLCH).set("l", luminance); | |
return { | |
tokenName: `${baseColorName}-${grade}`, | |
color: newColor, | |
}; | |
}); | |
} | |
function relativeLuminance(color) { | |
const rgbColor = color.toGamut({ | |
space: "srgb", | |
}); | |
return ( | |
0.2126 * rgbColor.srgb.r + | |
0.7152 * rgbColor.srgb.g + | |
0.0722 * rgbColor.srgb.b | |
); | |
} | |
function printHeaderRow() { | |
console.log(`Token\tHex\tRGBA\tOKLCH\tHSL\tLuminance`); | |
} | |
function printColorValues(token, color) { | |
const hex = color.to("srgb").toString({ format: "hex" }); | |
const rgba = color.to("srgb").toString({ format: "rgba" }); | |
const oklch = color.to("oklch").toString({ format: "oklch" }); | |
const hsl = color.to("hsl").toString({ format: "hsl" }); | |
const luminance = relativeLuminance(color); | |
console.log(`${token}\t${hex}\t${rgba}\t${oklch}\t${hsl}\t${luminance}`); | |
} | |
function printScaleTable(scale) { | |
scale.forEach((scaleItem) => { | |
printColorValues(scaleItem.tokenName, scaleItem.color); | |
}); | |
} | |
function printScaleCSSVariables(scale) { | |
scale.forEach((scaleItem) => { | |
console.log( | |
`--${scaleItem.tokenName}: ${scaleItem.color.to("oklch").toString({ format: "oklch" })};`, | |
); | |
}); | |
} | |
printHeaderRow(); | |
printScaleTable( | |
scaleForBaseColor( | |
"maryland-red", | |
marylandRedBase, | |
redCoolVividLuminanceMapping, | |
), | |
); | |
printScaleTable( | |
scaleForBaseColor( | |
"maryland-anti-red", | |
marylandAntiRedBase, | |
cyanLuminanceMapping, | |
), | |
); | |
printScaleTable( | |
scaleForBaseColor( | |
"maryland-gold", | |
marylandGoldBase, | |
yellowVividLuminanceMapping, | |
), | |
); | |
printScaleTable( | |
scaleForBaseColor( | |
"maryland-anti-gold", | |
marylandAntiGoldBase, | |
blueLuminanceMapping, | |
), | |
); | |
printScaleTable( | |
scaleForBaseColor("maryland-blue", marylandBlueBase, blueLuminanceMapping), | |
); | |
printScaleTable( | |
scaleForBaseColor("maryland-cyan", marylandCyanBase, blueLuminanceMapping), | |
); | |
console.log("\n\n\n"); | |
printScaleCSSVariables( | |
scaleForBaseColor( | |
"maryland-red", | |
marylandRedBase, | |
redCoolVividLuminanceMapping, | |
), | |
); | |
printScaleCSSVariables( | |
scaleForBaseColor( | |
"maryland-anti-red", | |
marylandAntiRedBase, | |
cyanLuminanceMapping, | |
), | |
); | |
printScaleCSSVariables( | |
scaleForBaseColor( | |
"maryland-gold", | |
marylandGoldBase, | |
yellowVividLuminanceMapping, | |
), | |
); | |
printScaleCSSVariables( | |
scaleForBaseColor( | |
"maryland-anti-gold", | |
marylandAntiGoldBase, | |
blueLuminanceMapping, | |
), | |
); | |
printScaleCSSVariables( | |
scaleForBaseColor("maryland-blue", marylandBlueBase, blueLuminanceMapping), | |
); | |
printScaleCSSVariables( | |
scaleForBaseColor("maryland-cyan", marylandCyanBase, blueLuminanceMapping), | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment