Generating colors with the CSS oklch() function
Did you know CSS is a programming language, actually?
A few weeks ago, I wrote about creating an accessible color palette using LCH. Today, I wanted to share how the CSS oklch() function makes that even easier!
Let’s dig in!
The CSS oklch() function
The CSS oklch() function is a CSS-based way to generate a color using the Oklab color space. You pass in the Lightness, Chroma, and Hue as arguments, and it generates the color.
This example generates a dark blue background from a base hue of 263, which translates to #004cff in hex.
I’m setting the lightness to 18.5%, and the chroma (how much color to include) to .1 or 10%.
.hero {
background-color: oklch(18.5% .1 263);
color: white;
}You’ll notice the hue isn’t a hex code. It’s the hue value on a 360 degree color wheel.
Newer browsers support relative colors with oklch(), where you can pass in a hex value and the function will convert it into LCH for you so that you can modify it.
.hero {
background-color: oklch(from #004cff 18.5% .1 h);
color: white;
}Creating a palette with oklch()
As I explained in my article on accessible color palettes, by adjusting the lightness and chroma, we can create a range of shades for a single color.
The oklch() function makes that even easier!
The original version of my theme builder for Kelp used JavaScript to generate a full suite of color variables from a hex value.
If you entered #0088cc, it would spit out something like this…
:root {
--color-blue-base: #0088cc;
--color-blue-05: #001432;
--color-blue-10: #002149;
--color-blue-20: #003671;
--color-blue-30: #004b94;
--color-blue-40: #005fb7;
--color-blue-50: #007ee0;
--color-blue-60: #009ef6;
--color-blue-70: #59b7f9;
--color-blue-80: #97d0fc;
--color-blue-90: #cee9fd;
--color-blue-95: #e7f4fe;
}You would then need to copy/paste that into your customizations file.
But using oklch(), all we need is the hue for the hex code. CSS can handle the rest.
:root {
--color-blue-base: #004cff;
--color-blue-hue: 263.27;
--color-blue-05: oklch(18.5% .08 var(--color-blue-hue));
--color-blue-10: oklch(24% .1 var(--color-blue-hue));
--color-blue-20: oklch(32.5% .135 var(--color-blue-hue));
--color-blue-30: oklch(40% .16 var(--color-blue-hue));
--color-blue-40: oklch(47% .185 var(--color-blue-hue));
--color-blue-50: oklch(57% .2 var(--color-blue-hue));
--color-blue-60: oklch(67% .175 var(--color-blue-hue));
--color-blue-70: oklch(75% .13 var(--color-blue-hue));
--color-blue-80: oklch(83.5% .085 var(--color-blue-hue));
--color-blue-90: oklch(92% .04 var(--color-blue-hue));
--color-blue-95: oklch(96% .02 var(--color-blue-hue));
}If you wanted to change the color, all you need to do now is update the --color-blue-hue variable, and oklch() handles the rest.
(The --color-blue-base variable is there for reference only.)
:root {
--color-blue-base: #0088cc;
--color-blue-hue: 241.55;
}I’ve already update the Kelp Theme Builder to use this approach.
Adjusting brightness/saturation
One other aspect of color is how saturated it is. The same hue looks a lot more muted with the chroma turned down, and looks a lot more vibrant with it turned up.
CSS can handle this for us, too!
If we set a --color-*-chroma variable, we can combine it with the CSS calc() function to do math for us and adjust the chroma up or down.
I include a default value of 1…
:root {
--color-blue-base: #004cff;
--color-blue-hue: 263.27;
--color-blue-chroma: 1;
}And multiply the default chroma value by it in the CSS.
:root {
--color-blue-05: oklch(18.5% calc(.08 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-10: oklch(24% calc(.1 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-20: oklch(32.5% calc(.135 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-30: oklch(40% calc(.16 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-40: oklch(47% calc(.185 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-50: oklch(57% calc(.2 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-60: oklch(67% calc(.175 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-70: oklch(75% calc(.13 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-80: oklch(83.5% calc(.085 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-90: oklch(92% calc(.04 * var(--color-blue-chroma)) var(--color-blue-hue));
--color-blue-95: oklch(96% calc(.02 * var(--color-blue-chroma)) var(--color-blue-hue));
}If you adjust --color-blue-chroma, you’ll get a different color palette, without changing the hue.
:root {
/* more muted */
--color-blue-chroma: 0.5;
/* more vibrant */
--color-blue-chroma: 1.25;
}You can play around with this in the Kelp Theme Builder right now.