The New CSS Color Format You Didn't Know You Needed; OKLCH()
Tags: css, tailwindcss, oklch, color
Published: 2024-01-24 17:48:34

**T**he other day, I was on [uicolors](https://uicolors.app/create) trying to find a suitable color scheme to base a current project's theme off of. The client requested a muted green as the primary color and so I derived that using a dropper tool to extract a hexadecimal code. I plugged that hex code into [uicolors](https://uicolors.app/create) (srsly, that site is great) and got my palette. I then went to export the necessary code to plug in to my tailwind config file when I noticed this abomination of a format: 

---

![OKLCH syntax I came across that blew my mind at first glance](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/miv3ak8l4028g9bih3zj.JPG)

---

## **WHAT IN THE HECK IS THAT???**

---

Needless to say, I had to drop everything I was doing and hyperfixate on this new color format I'd never heard of and/or confirm to myself I wasn't having an existential crisis due to not being aware of OKLCH's long and storied existence (spoiler: it became accepted on all browsers in September 2023 and was only [proposed](https://www.youtube.com/watch?v=dOsp6u4bIwI&t=241s) to [W3C](https://www.w3.org/about/) back in 2021).

---

Now that my mental crises have been averted, what even is `oklch()` and why does it exist? We already have so many color formats in CSS and this just seems like yet another thing I need to know about for some ridiculous and arbitrary reason.

I mean, we already have:


- Hexadecimal `#663399`
- RGB/a : `rgba(102, 51, 153, 1)`
- HSL/a : `hsla(270, 50%, 40%, 1)`
- HSV : `hsv(270, 67%, 60%)`
- HWB : `hwb(270, 20%, 40%)`
- Many More I'm Forgetting (color keywords don't count)

> (All of the above color codes are [rebeccapurple](https://medium.com/@valgaze/the-hidden-purple-memorial-in-your-web-browser-7d84813bb416); if you feel like a good cry today, read that link)


So **WHY** do we need any more color formats to confuse us with?? That exact question was the second portion of my hyperfixation search, which I'm hoping to condense in easy-to-reason-about terms and save you the precious time you probably need for a myriad of other things, like, oh I don't know, living a life, spending time with loved ones, etc., ad nauseum.

Let's dive into it:

---

##WHY DOES `oklch()` EVEN EXIST?

---


Before we can dive into why `oklch()` exists, we first need to talk about its ancestor, `lch()`:

lch stands for: 
- Lightness
- Chroma
- Hue


Much like `hsl()` (which stands for hue, saturation and lightness), `lch()` allows you to configure three separate parameters to determine the:

 - brightness (l) 
 - intensity/saturation (c)
 - color (h)

However, there are two key differences that `lch()` possesses that `hsl()` does not:

---

1. Homogeneous brightness <u>perception</u> by a human from any given color on a screen

2. `lch()` isn't bound to any one color space

---

**So what exactly do those previous two points mean?**

---

To address the first point, it's basically what it sounds like; when you, I or anyone else that falls under the category of being a human perceives some color on a screen that's from the Internet, there exists the possibility that two colors with the same lightness value in `hsl()` will be perceived differently due to their intrinsic hue (or color) value.

Josh Comeau relays this _perfectly_ in his blog [post](https://www.joshwcomeau.com/css/color-formats/#lch-7) on css color formats. You can even see the difference between `hsl()` and `lch()` and how one color seems brighter than the other, even though their lightness values are identical in `hsl()`.

**_That's_** what is meant by <u>perception</u>; the incredibly complex anatomy that our eyes have developed over eons to perceive lightness via [rods](https://en.wikipedia.org/wiki/Rod_cell) and color via [cones](https://en.wikipedia.org/wiki/Cone_cell) doesn't work well with the mathematical formula found in the `hsl()` format.

---

**__Wild__ stuff, right?**

---

To address the second point on `lch()` not being bound to any one color space, basically all that means is that the color it produces will appear identical, regardless of what type of screen is displaying it.

The majority of today's screens use a color space known as [sRGB](https://en.wikipedia.org/wiki/SRGB). sRGB has been the standard for quite some time and for the most part, it has served its purpose well.

There also exists another color space that's slowly becoming the new standard, however. That color space is called [DCI-P3](https://en.wikipedia.org/wiki/DCI-P3) or simply, P3. It has its roots in cinematic displays for defining a color standard for digital movies to be displayed with.

This is all to say that regardless of what type of color space your screen is using, `lch()` will produce a perceptually identical color, no matter what.

And you wanna know what's even more mind-blowing about `lch()`? Because it isn't tied to any one color space, the upper-limit for its chroma (or saturation) value **isn't even _known_**. That ultimately amounts to _guaranteed_ color perception on virtually *ANY* screen until we discover the limit that's intrinsic to `lch()`.

---

##**_WILD_ STUFF RIGHT??**

---

**Okay**, now that we've touched on the basics of `lch()`, why is there a need for this new, arcane color format known as `oklch()`? 

The main reason is a flaw found in `lch()` where blue appears to be more of a purple when adjusting the lightness value. You can read more about that in an article written by Vojtěch Vidra and Ondřej Pešička [here](https://atmos.style/blog/lch-vs-oklch).

Aside from that, there isn't much of a difference between the two....

##**UNLESS YOU'RE A TAILWIND USER**

That's right, if you have yet to use Tailwind in your projects, please allow me to offer yet another compelling reason as to why you should consider it:

---
##**DYNAMIC COLOR THEMES**
---

What are dynamic color themes you ask?

The website Evil Martians has a great [post](https://evilmartians.com/chronicles/better-dynamic-themes-in-tailwind-with-oklch-color-magic) detailing this, but ultimately, using `oklch()` in conjunction with Tailwind allows for some pretty powerful dynamic color theme generations.

One such use-case can be found in allowing end-users to define what color scheme they prefer for their application's UI, which is demonstrated beautifully by Evil Martians' [post](https://evilmartians.com/chronicles/better-dynamic-themes-in-tailwind-with-oklch-color-magic) in the previous paragraph.

Essentially all that's needed is an array to define the various chroma values you wish to use. Tailwind comes with out-of-the-box shade generation for any given color, so determining lightness values within an array isn't necessary. Simply choose your desired primary colors and you'll have all possible ranges of those primary colors for the user to choose from via a color slider placed in the UI.

Obviously, implementing the color slider and some more intricacies are needed, but a LOT of the heavy lifting is abstracted away for you thanks to Tailwind and `oklch()`. And to emphasize it _yet_ again, check out that [article](https://evilmartians.com/chronicles/better-dynamic-themes-in-tailwind-with-oklch-color-magic) from Evil Martians if you wish to actually implement that.

And to make that even more of a reality, there exists an `oklch()` [color picker](https://oklch.com/) to determine _precisely_ the values you need to generate an entire palette.

---

And that's pretty much all I have to say on that.

 If you're interested in diving more into these two color formats, you can check out the CIELAB Wikipedia [page](https://en.wikipedia.org/wiki/CIELAB_color_space), which is the organization that developed `lch()` in 1976(??), or check out [Björn Ottosson](https://bottosson.github.io/posts/oklab/), who developed the new `oklch()` format in 2020. His proposal can be found in the recently updated [CSS Color 4 module](https://www.w3.org/TR/css-color-4/#ok-lab).

Thanks for sticking with me through my hyperfixations and crises, as always!

<3<3