Last active
March 16, 2023 22:28
-
-
Save ErickPetru/d56a698f6600d19697181fa475671ce5 to your computer and use it in GitHub Desktop.
Extract CSS custom properties (CSS variables) from Tailwind Color Palette by Web scrapping its documentation
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
/* Extract CSS custom properties (CSS variables) from Tailwind Color Palette | |
* Navigate to: https://tailwindcss.com/docs/customizing-colors | |
* Then open browser's console and run the following code | |
*/ | |
const palette = [ | |
...document | |
.querySelector("#content-wrapper > .grid.grid-cols-1") | |
.querySelectorAll(".flex.flex-col.space-y-3"), | |
] | |
.map((row) => ({ | |
color: row | |
.querySelector(".w-16.shrink-0") | |
.textContent.toString() | |
.toLowerCase(), | |
shades: [...row.querySelectorAll(".relative.flex > .cursor-pointer")].map( | |
(color) => ({ | |
shade: color.querySelector(".font-medium").textContent.toString(), | |
rgb: color | |
.querySelector(".h-10") | |
.style.backgroundColor.replace(/[rgb|(|)|,]/g, "") | |
.replace(")", ""), | |
hex: color | |
.querySelector(".font-mono") | |
.textContent.toString() | |
.toLowerCase(), | |
}) | |
), | |
})) | |
.reduce( | |
(acc, curr) => ({ | |
...acc, | |
[curr.color]: curr.shades.reduce( | |
(acc2, curr2) => ({ | |
...acc2, | |
[curr2.shade]: { rgb: curr2.rgb, hex: curr2.hex }, | |
}), | |
{} | |
), | |
}), | |
{} | |
); | |
console.log( | |
Object.keys(palette) | |
.map( | |
(color) => | |
`/* ${color[0].toUpperCase()}${color.substr(1)} */\n` + | |
Object.keys(palette[color]) | |
.map( | |
(shade) => | |
`--color-${color}-${shade}-rgb: rgb(${palette[color][shade].rgb});\n--color-${color}-${shade}-hex: ${palette[color][shade].hex};` | |
) | |
.join("\n") | |
) | |
.join("\n\n") | |
); |
Generating a new 950
shade for each color, and outputting a reversed color palette for automatic dark themes:
function getLowestMiddleHighest(rgbArray) {
let highest = { val: -1, index: -1 };
let lowest = { val: Infinity, index: -1 };
rgbArray.forEach((val, index) => {
if (val > highest.val) highest = { val: val, index: index };
if (val < lowest.val) lowest = { val: val, index: index };
});
if (lowest.index === highest.index) {
lowest.index = highest.index + 1;
}
const middle = { index: 3 - highest.index - lowest.index };
middle.val = rgbArray[middle.index];
return [lowest, middle, highest];
}
function darken(color) {
const rgbArray = [...color.rgb.matchAll(/(\d+),? (\d+),? (\d+)/gi)][0]
.slice(1)
.map((n) => parseInt(n, 10));
const [lowest, middle, highest] = getLowestMiddleHighest(rgbArray);
if (highest.val === 0) return color;
const result = [];
const deviation = highest.val > 50 ? 30.5 : 12.5;
result[highest.index] = highest.val - Math.min(highest.val, deviation);
const decreaseFraction = (highest.val - result[highest.index]) / highest.val;
result[middle.index] = middle.val - middle.val * decreaseFraction;
result[lowest.index] = lowest.val - lowest.val * decreaseFraction;
return {
rgb: `${result.map((n) => Math.round(n).toString(10)).join(" ")}`,
hex: `#${result.map((n) => n.toString(16).padStart(2, "0")).join("")}`,
};
}
const palette = [
...document
.querySelector("#content-wrapper > .grid.grid-cols-1")
.querySelectorAll(".flex.flex-col.space-y-3"),
]
.map((row) => ({
color: row
.querySelector(".w-16.shrink-0")
.textContent.toString()
.toLowerCase(),
shades: [...row.querySelectorAll(".relative.flex > .cursor-pointer")].map(
(color) => ({
shade: color.querySelector(".font-medium").textContent.toString(),
rgb: color
.querySelector(".h-10")
.style.backgroundColor.replace(/[rgb|(|)|,]/g, "")
.replace(")", ""),
hex: color
.querySelector(".font-mono")
.textContent.toString()
.toLowerCase(),
})
),
}))
.reduce(
(acc, curr) => ({
...acc,
[curr.color]: curr.shades.reduce(
(acc2, curr2) => ({
...acc2,
[curr2.shade]: { rgb: curr2.rgb, hex: curr2.hex },
}),
{ 950: darken(curr.shades[curr.shades.length - 1]) }
),
}),
{}
);
console.log(
Object.keys(palette)
.map(
(color) =>
`/* ${color[0].toUpperCase()}${color.substring(1)} */\n` +
Object.keys(palette[color])
.map(
(shade) =>
`--color-${color}-${shade}: rgb(${palette[color][
shade
].rgb.replaceAll(" ", ", ")});`
)
.join("\n")
)
.join("\n\n")
);
const reversedShade = {
50: "950",
100: "900",
200: "800",
300: "700",
400: "600",
500: "500",
600: "400",
700: "300",
800: "200",
900: "100",
950: "50",
};
console.log(
Object.keys(palette)
.map(
(color) =>
`/* ${color[0].toUpperCase()}${color.substring(1)} */\n` +
Object.keys(palette[color])
.map(
(shade) =>
`--color-${color}-${reversedShade[shade]}: rgb(${palette[color][
shade
].rgb.replaceAll(" ", ", ")});`
)
.reverse()
.join("\n")
)
.join("\n\n")
);
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Results targeting TailwindCSS Colors right now: