Skip to content

Instantly share code, notes, and snippets.

@brookback
Created February 26, 2020 22:25
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 brookback/ac1205d1191e78bdaf24e476a04c440d to your computer and use it in GitHub Desktop.
Save brookback/ac1205d1191e78bdaf24e476a04c440d to your computer and use it in GitHub Desktop.
PostCSS plugin which finds all hex or rgb colors defined on :root, and converts them to Display P3 versions and adds to a @supports rule.
:root {
--sans: Quicksand, sans-serif;
--serif: Neuton, serif;
--font-size: 24px;
--lineheight: 1.6;
--spacing: calc(var(--lineheight) * 1rem);
/* Colours */
--coral: #dd7e70;
--brown: #563400;
--blue: #aed9e0;
--blue-dark: #24586c;
--gray: #5e6472;
--green: #dfece5;
--beige: #faf3dd;
--beige-dark: #5b482c;
--salmon: #fdf0e6;
--background: #fbfbf5;
--body-color: var(--beige-dark);
--main-heading-size: calc(100 / var(--font-size) * 1rem);
}
:root {
--sans: Quicksand, sans-serif;
--serif: Neuton, serif;
--font-size: 24px;
--lineheight: 1.6;
--spacing: calc(var(--lineheight) * 1rem);
/* Colours */
/* https://coolors.co/f08e80-faf3dd-dfece5-aed9e0-5e6472 */
--coral: #dd7e70;
--brown: #563400;
--blue: #aed9e0;
--blue-dark: #24586c;
--gray: #5e6472;
--green: #dfece5;
--beige: #faf3dd;
--beige-dark: #5b482c;
--salmon: #fdf0e6;
--background: #fbfbf5;
--body-color: var(--beige-dark);
--main-heading-size: calc(100 / var(--font-size) * 1rem);
}
@supports (color: color(display-p3 1 1 1 / 1)){
:root{--coral: color(display-p3 0.8666666666666667 0.49411764705882355 0.4392156862745098 / 1);--brown: color(display-p3 0.33725490196078434 0.20392156862745098 0 / 1);--blue: color(display-p3 0.6823529411764706 0.8509803921568627 0.8784313725490196 / 1);--blue-dark: color(display-p3 0.1411764705882353 0.34509803921568627 0.4235294117647059 / 1);--gray: color(display-p3 0.3686274509803922 0.39215686274509803 0.4470588235294118 / 1);--green: color(display-p3 0.8745098039215686 0.9254901960784314 0.8980392156862745 / 1);--beige: color(display-p3 0.9803921568627451 0.9529411764705882 0.8666666666666667 / 1);--beige-dark: color(display-p3 0.3568627450980392 0.2823529411764706 0.17254901960784313 / 1);--salmon: color(display-p3 0.9921568627450981 0.9411764705882353 0.9019607843137255 / 1);--background: color(display-p3 0.984313725490196 0.984313725490196 0.9607843137254902 / 1);
}
}
const postcss = require('postcss');
const SHORTHAND_HEX_REGEX = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
const HEX_REGEX = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
/** PostCSS plugin which finds all hex or rgb colors defined on :root, and
* converts them to Display P3 versions and adds to a @supports rule.
*/
module.exports = postcss.plugin('postcss-p3', () => {
return (css) => {
const p3colors = [];
css.walkRules(':root', (rule) => {
rule.walkDecls((decl) => {
if (isHex(decl.value)) {
const p3version = postcss.decl({
prop: decl.prop,
value: toColorProfile(decl.value),
});
p3colors.push(p3version);
}
});
});
const root = postcss.rule({
selector: ':root',
nodes: p3colors,
});
const supports = postcss.atRule({
name: 'supports',
params: '(color: color(display-p3 1 1 1 / 1))',
});
supports.append(root);
// Just add after first root
css.walkRules(':root', (rule) => {
rule.after(supports);
return false;
});
console.log(`Done. Converted ${p3colors.length} colours to P3`);
};
});
const isHex = (colorName) => /^#[a-f\d]/i.test(colorName);
const hexToRgb = (hex) => {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
hex = hex.replace(SHORTHAND_HEX_REGEX, (_, r, g, b) => {
return r + r + g + g + b + b;
});
const result = HEX_REGEX.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
};
const toColorProfile = (color, colorProfileName = 'display-p3') => {
const rgb = isHex(color) ? hexToRgb(color) : color; // assume rgb
if (!rgb) {
console.warn(
`Skipping converting ${color} to Display P3 as it's ${rgb} when converted to RGB.`
);
return color;
}
const r = rgb.r / 255;
const g = rgb.g / 255;
const b = rgb.b / 255;
// color(p3 1.0 0 0 / 1);
return `color(${colorProfileName} ${r} ${g} ${b} / 1)`;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment