← All videos

Stop writing your websites in hexcodes

Hex codes can't name the colors modern screens show beyond sRGB. OKLCH can, and Tailwind v4's palette uses it. HSL's lightness isn't how light a color looks, so text readable in one HSL color can vanish in another. OKLCH's is a much better start.

quant anime13:39Watch on YouTube
Contents

From hex to OKLCH0:00

Yo guys? What is up? David here. If you're a designer or a developer, you may have noticed some tools now hand you a colour as something called OKLCH, before they give you the hex code. If you're a vibe coder building a website this year, there's a decent chance its colours are in that format too. We checked public projects exported from one popular AI site builder. In spring 2025, none of 102 used it.

By the autumn, 39 of 52 did. If something changes an AI's mind that quickly, it's worth asking why. In this case, it was the template. And that template traces back to a blog post, posted two days before Christmas 2020, by one engineer on his own time. This is how someone's unpaid hobby project changed computer graphics.

What OKLCH fixes0:47

Here's what OKLCH actually looks like. A colour space is just a way of writing every colour as numbers. OKLCH uses three parameters. Lightness is how light the colour looks, from black at 0% to white at 100%. Chroma is how colourful it is, where 0 is grey. And hue is an angle around the colour wheel. Tailwind CSS writes its red-500 at about 64% lightness and its blue-500 at about 62%.

So to your eye, that red and that blue are almost equally light. That's the whole promise. Turn only the hue dial, and you get a different colour that looks just as light and just as colourful. Now compare that to what most of us grew up with. Hex codes and RGB just tell the screen how much red, green and blue light to give off. To make that friendlier, design tools gave us HSL and HSV, with sliders for hue, saturation and lightness.

Something to note, HSL's lightness isn't how light the colour looks to you. It's a formula on the screen's numbers. Take the six pure colours HSV calls equally bright. Measure how light they actually look, and yellow comes out at 0.97 while blue is down at 0.45. That's half the whole scale, between colours that are supposed to match. That's also why text that's readable on one HSL colour can vanish on another.

Six colours, measured
0.63Red
0.97Yellow
0.87Green
0.91Cyan
0.45Blue
0.70Magenta

Bar height is how light each colour measures in Oklab. Spread: 0.52

In OKLCH, keeping the lightness the same is a much better starting point, though strongly coloured shades can still look a little brighter than their number. Mixing goes wrong too. Blend two strong opposite colours in screen numbers, and the middle goes muddy, darker and bluer than either. The same problem shows up the moment you ask a computer for a random colour, say, to colour a crowd of objects in a game.

The same two colours, mixed three ways
lightness 0.87 and 0.70
Screen numbers
middle #808080 · L 0.60
Real light
middle #bcbcbc · L 0.79
Oklab
middle #c6b4b4 · L 0.78

We measured it, with 100,000 random colours per method. Pick random RGB numbers, and the colours aren't fair. Some hues come up five times as often as others, and the lightness wanders all over the place, so they never look like a family. Pick random HSV, and it's worse, darker, and about 4 in 10 come out nearly grey. Even random OKLCH numbers go grey, if you let every dial roam.

The trick is to fix the lightness and the colourfulness in OKLCH, and randomise only the hue. Every colour then comes out equally light and equally colourful. So why not just mix real light, photon for photon? Think of a volume knob. Going from a whisper to normal talking feels huge. Going from loud to slightly louder and you barely feel the difference. Your ear squashes the top end. Your eye does the same with light.

Ask for a random colour
Nearly grey: …Commonest hue vs rarest: …

Counted live in your browser over 100,000 colours.

Going from 10% of white's light to 20% looks like a step of about 14 on a lightness scale of 100. Going from 90% to 100% looks like a step of about 4. So a grey that gives off half the light of white doesn't look half as light. It looks three quarters of the way to white. Mix light honestly, and your gradients come out too bright in the middle.

The fix isn't better physics. It's about having a scale built on what your eye reports.

How we see colour3:39

So where does colour actually happen? Newton already said it in 1704. The rays themselves, he wrote, are not coloured. They just have the power to stir up a sensation of colour. That sensation starts with three kinds of cone in your eye. When they were first measured one by one, in 1964, their peaks sat in the yellow, the green and the violet. So the so-called red cone actually peaks in yellow-green.

Every light that hits your eye, however complicated, gets boiled down to three cone signals. That's why two completely different lights can look identical, which is called a metamer. It is also why a screen gets away with only three lights, red, green and blue, spread far enough apart to push each cone as separately as they can. So screens are built around our biology, not just around physics. We should also note not everyone has the same mix.

Among men with normal colour vision, the ratio of two of the cone types varies more than thirtyfold. Colour blindness is part of the same story. About 8% of men of European descent have red-green colour deficiency. Now let us go back in time for two old theories. They explain the rest, and it turns out both of them are right. In 1801, Thomas Young guessed the eye has only a few kinds of colour receptor.

He named red, yellow and blue, not red, green and blue, but the idea of three stuck. In 1874, Ewald Hering noticed something three receptors don't explain. Nothing ever looks reddish-green or yellowish-blue. So he proposed opponent pairs, black against white, red against green, blue against yellow, where the two ends of each pair cancel instead of mixing. Today we know the cones give you three signals, and the cells behind them compare those signals in opposing pairs.

Oklab follows that order. A step that makes three cone-like signals, a squash for the volume-knob effect, and a step that turns them into lightness and two opponent axes. Those axes are fitted, though, not a copy of the brain's own wiring.

A century of rulers5:33

For about a century, people tried to put colour on a ruler. The master standard, from 1931, rests on colour-matching experiments. One of the two key datasets came from just 10 observers. In 1942, one researcher ran over 25,000 matches on a single person, and showed the 1931 chart can't be redrawn to make equal differences look equal. By the 1970s industries were using as many as 20 different formulas for colour difference.

So in 1976 the CIE, the international body for light, recommended two spaces at once. CIELAB for dyes and textiles, and CIELUV for TV. On how well they matched people's judgments of colour differences, they scored almost exactly the same. Then computers went their own way. HSV, from 1978, was a fast shortcut for paint programs, and its author said plainly he was skipping full colour theory. And sRGB, from 1996, was HP and Microsoft describing the average PC screen, which the web adopted six weeks later.

None of these were mistakes. They were built for dyes, TV, speed and old screens. They just weren't built to match your eye. One colour kept breaking things. That color is blue. Here's how people found it. In a 1995 experiment, 9 observers adjusted colours on a screen until each matched a reference hue, tracing 24 lines of what looked like one constant hue. Then you check whether a colour space keeps each line at one hue angle.

CIELAB didn't, and the errors were biggest near blue. Add white to a blue, and the old maths still calls it the same hue, while your eye watches it turn purple. That one flaw shows up everywhere. The 2000 colour-difference formula needed a special patch just for blue. And the web's own standard says doing this kind of maths in the old space gives significant hue shifts in the blues and purples.

So how do you build something better? You don't start from zero. One man took the simple structure of an older space called IPT, built in 1998 to keep hues constant, and aimed it at the accuracy of CAM16, a heavy model that also accounts for viewing conditions. He fitted it to three sets of colour pairs. Pairs of equal lightness and pairs of equal colourfulness, both generated by CAM16, and the real hue matches behind IPT.

The squash in the middle came out almost exactly a cube root. The fit gave 0.32, and he rounded it to a third, partly so blue wouldn't fold in on itself. On his own test, Oklab's lightness error is 0.2, against 1.7 for CIELAB and 11.6 for HSV. But here's his own caveat. Because those pairs came from CAM16 and not from new experiments with people, he writes that his numbers can't say which model best matches human perception.

He wanted the original experimental data, but he couldn't find it.

One engineer's post8:19

So who is he? His name is Björn Ottosson, based in Stockholm. For a bit more than a decade, until 2020, he worked at DICE on EA's Frostbite engine, on games like Battlefield, Star Wars Battlefront, Need for Speed and FIFA. The itch came from that job. He just wanted to make a colour darker, or change its hue, without everything going wrong. When he left to teach and consult, he finally had time to fix it.

He called it Oklab, because, in his words, it is an OK Lab colour space. He put the code in the public domain. And his whole colour writing is four blog posts in 10 months. Today, he's working on a solo city-building game. You can show him some support, his link is in the description. Anyway, the post went up on 23 December 2020, and it was on Hacker News the next day.

On New Year's Day, an Apple engineer pointed it out to the W3C's colour lead. By October 2021, the group that writes the web's styling rules voted it in. That same month, Photoshop made it the default way gradients blend. Then came Unity, Godot and ImageMagick, and every major browser by 2023. He says it all happened without him having to cheer it on. I haven't seen something taken up this quickly.

This is the kind of success that makes a developer like me envious, considering how much I've spent on ads to get people to notice my business, and how few people follow my channels and Twitter. Link in the description, for those interested. There's a twist. Sometimes massive success brings a different kind of problem. In his case, Ottosson found a flaw in work he'd already released. In October 2021, Ottosson told the standards group that one of his scaling factors was off by quite a bit.

He hadn't checked it carefully, because he didn't expect it to spread so widely so quickly. He even floated a second version. It never came. By then too much depended on the first one, so the web standard kept Oklab as it was and added a new way of measuring colour difference on top. When nobody uses your code, you can change it whenever you like. When everybody does, it freezes.

How did they manage that without thousands of Jira tickets and merge requests?

Your AI and the limits10:23

Now let us talk a bit about AI. In January 2025, Tailwind switched its whole default palette to OKLCH. Their reason was more vivid colours on modern screens, not perceptual evenness. Modern phones and laptops can show colours outside sRGB. A hex code can't name them, because hex lives inside sRGB. An OKLCH value can. A month later, shadcn, a component kit built on Tailwind, followed. And v0, Vercel's AI site builder, says it uses both.

That's the jump from none of 102 projects to 39 of 52. Builders still on the older template, like Lovable and Bolt, show zero. Interestingly, Anthropic's own published design guidance for Claude still asks for hex codes. Someone tell Claude to revise its design.md to OKLCH. Last time I checked, across the whole web, Chrome now sees it on 3.6% of page loads, up from 0.8% at the start of 2025.

We talked a lot about computer graphics, can this lesson be applied to computer vision? Mostly, no. Feed an image classifier 10 different colour spaces, and its accuracy barely moves, between about 79% and 80%. Networks even invent their own opponent-like colour channels. Oklab is about people. The neatest proof is a system called Revelio, which hides data in a flicker built in Oklab. A phone camera and a neural network can read it.

People can't see it. Cameras are the better photon counters. We're the ones with blind spots, and Oklab is built around ours. Even then, approximated human perception isn't perfect. One reviewer finds it a little darker than CIELAB, though he still recommends it for making better gradients. The W3C's colour lead calls it a standard for ordinary screens only, not HDR. And designers editing OKLCH by hand keep landing on colours their screen can't show.

Some things it doesn't model at all. Luminance, which is light weighted by how sensitive your eye is, still isn't how light something looks. Strongly coloured things look brighter than their luminance says, and Oklab, copying CAM16, ignores that. Nor does it know what colours sit next to each other, which changes what you see.

What to take away12:32

For those who just want a takeaway, here it is. If you write graphics code, build gradients, or do procedural generation for game assets, do your colour maths in Oklab. In CSS, write your gradient stops in OKLCH, because hex stops still blend the old way, and let CSS mix them in Oklab, which it does by default. If you ask it to mix in OKLCH, the gradient swings round the colour wheel on the way.

If you're working on computer vision, you can safely ignore all of this. And notice how all of this happened. One person, on his own time, went back through a century of colour science, took the best pieces the committees had already built, and reasoned it through. You don't need a big lab, a big team, a big budget, or all the credentials people say you need to be an authority.

Often, just showing some obsession in your work is the best thing you can have. Sometimes, it even changed the defaults for everyone. Thanks for watching and I will see you guys next time.

Sources

  1. Ottosson, "A perceptual color space for image processing" (2020)
  2. Ottosson, "How software gets color wrong" (2020)
  3. Jägenstedt, "Interview With Björn Ottosson, Creator Of The Oklab Color Space", Smashing Magazine (2024)
  4. CSS Working Group issue #6642, "Add OKLab, OKLCH" (2021)
  5. W3C, CSS Color Module Level 4
  6. Tailwind CSS v4.0 (2025)
  7. shadcn/ui, Tailwind v4 changelog (2025)
  8. Anthropic, frontend-design skill
  9. Chrome usage of oklab()/oklch()
  10. Newton, Opticks (1704)
  11. Marks, Dobelle & MacNichol (1964), single primate cones
  12. Carroll, Neitz & Neitz (2002), L:M cone ratio
  13. MacAdam (1942), "Visual sensitivities to color differences in daylight"
  14. Robertson (1977), "The CIE 1976 color-difference formulae"
  15. Smith (1978), "Color Gamut Transform Pairs" (HSV)
  16. Stokes et al. (1996), sRGB
  17. Hung & Berns (1995), constant hue loci
  18. Ebner & Fairchild (1998), IPT
  19. Li et al. (2017), CAM16
  20. Gowda & Yuan (2019), ColorNet
  21. Krizhevsky, Sutskever & Hinton (2012), AlexNet
  22. Nishar et al. (2025), Revelio
  23. Levien (2021), "An interactive review of Oklab"
  24. Coyier (2023), "Two Things That are Not Great About OKLCH"

@nelvOfficial · Q3D Research