Glance at the summary firstThe summary from the end of the lesson, as a road map before you start reading.
- CIELAB's hue linearity isn't complete; especially in blues, hue drifts as lightness or chroma changes, and a transition from blue to white veers toward purple.
- Interpolation done in gamma-encoded sRGB leads to a dark gray between complementary colors and to muddy intermediate tones in other pairs; OKLab keeps the midpoint at the perceptual average lightness and removes false hue shifts, while OKLCh also preserves colorfulness by traveling around the circle.
- Representations like PQ, ICtCp, and Jzazbz were developed for HDR to account for a much wider brightness range; OKLab, meanwhile, became the default interpolation space on the web, but it's not a color appearance model, and older sRGB syntaxes are still blended in sRGB.
Short answer
When a gradient is drawn between two colors on screen, the calculation is usually done on gamma-encoded sRGB values; in this space, the exact midpoint between two complementary colors lands on a gray that is darker than it should be. OKLab is a space that scales lightness to match how the eye perceives it and keeps hue more consistent than CIELAB does; because of this, the gradient's midpoint stays at the expected lightness and false hue shifts, like the drift toward purple in a blue-to-white transition, disappear; to also preserve colorfulness between complementary colors, the calculation is done in OKLCh, OKLab's polar form, by traveling around the circumference of the color wheel. For HDR, that is, high-dynamic-range content, spaces like Jzazbz and ICtCp were developed that account for a much wider brightness range.
Why wasn't CIELAB enough?
As you saw in BI-19, CIELAB has been the common language for measuring color differences since 1976. But its perceptual uniformity isn't complete, and this shortcoming is pronounced in certain regions, especially in blues.
The best-documented form of the problem is hue linearity. In an ideal space, as you move along a fixed hue angle from the neutral axis toward the most saturated color, the perceived hue shouldn't change: a blue should look like the same blue whether it's pale or vivid. In a study published in 1995, Hung and Berns used matches made by nine observers on a screen to establish 24 constant-hue loci and compared these to the hue angles of CIELAB and other spaces. They found that in CIELAB, the perceived hue clearly drifted as you moved along a fixed hue angle from neutral toward the highest chroma, with the largest errors in the region of the screen's blue primary.
In practice, this means a blue drifts toward a purplish hue as you lighten it in CIELAB or mix it with white. You can see this in numbers too. If you calculate a transition from the screen's pure blue (#0000FF) to white in CIELAB and measure the intermediate points with OKLab's hue angle, the angle comes out at 288° a quarter of the way, 298° halfway, and 303° three-quarters of the way; the blue drifts step by step toward purple. When the same transition is calculated in OKLab, the angle stays steady at around 264°, 263°, 261°.
More elaborate color appearance models were built to solve these problems, for example CAM16 and its uniform space CAM16-UCS; these also account for viewing conditions and are the subject of BI-22. But these models are computationally heavy and more complex than a simple blend or gradient needs. Image processing and interface design needed a space as simple as CIELAB but more accurate.
The gradient question: why does the middle turn gray?
The question on the lesson card is the most visible form of this need: why does a gradient turn gray in the middle, and how does OKLab solve it?
A gradient is a matter of producing intermediate colors between two colors; this is called interpolation. When the computer calculates these intermediate colors, it blends the numbers of the two colors in certain proportions. What the result turns out to be depends on which numbers, that is, which color space, they're blended in.
For a long time, the web's and most software's default route was to blend gamma-encoded sRGB values directly. With this method, the exact midpoint of a gradient from pure blue (#0000FF) to pure yellow (#FFFF00) is #808080: a flawless middle gray. Blue and yellow are complementary; each of the three color channels is 0 at one end and 255 at the other, and at the exact middle each channel falls to 128. What's more, this gray is darker than the average of the two ends' perceptual lightness. On OKLab's lightness scale, blue's lightness is about 0.45 and yellow's is 0.97; their average is 0.71, while sRGB's middle gray sits at 0.60. The gradient's midpoint looks both colorless and like a dark pit.
The same problem shows up as muddy intermediate tones in non-complementary colors too. Going from red (#FF0000) to green (#00FF00) in sRGB, the midpoint is #808000: a dark, olive-colored brown, with a lightness of 0.58. The two ends have lightness values of 0.63 and 0.87; the midpoint is darker than both.
Why? Gamma-encoded sRGB values aren't linear with the amount of light; this encoding, the subject of EK-05, compresses values to match the eye's sensitivity to dark tones. Averaging two encoded values gives neither the physical average of the lights nor the average of the perception; it gives something in between, usually a result darker than it should be.
Blending the same two ends in different spaces gives the following results. Blended in linear light values, the blue-yellow midpoint is #BCBCBC: still gray, but this time too light, at 0.79. Blended in CIELAB, the midpoint is #CA8AAA: not gray at all, but an unexpectedly pinkish tone, because CIELAB's curved hue structure routes the straight line through the purple region. Blended in OKLab, the midpoint is #6CABC7: its lightness is exactly 0.71, that is, the perceptual average of the two ends; its hue is a pale blue, with no false pinkness. For the red-green pair too, OKLab's midpoint is #D0A800, with a lightness of 0.75, a markedly brighter golden yellow than sRGB's muddy olive.
But it's worth being honest here. In OKLab, the chroma of the blue-yellow midpoint is still low: 0.077, about a quarter of the ends' chroma. This isn't a flaw in the space, it's geometry. OKLab has opponent axes just like CIELAB, and the straight line joining two complementary colors passes close to the neutral axis. If you want the midpoint to stay colorful, you have to travel around the circumference of the wheel instead of taking the straight line.
When the blue-yellow gradient is calculated in OKLCh with hue taking the short way around, the midpoint is #00CFBD: a vivid turquoise with a chroma of 0.136. The gradient now passes through greenish blues instead of gray. This, too, is a choice: which half of the color wheel to travel through is up to the designer. What OKLab solves is the gradient's false darkness and false hue shifts; the gray between complementary colors is overcome only through polar interpolation.
How was OKLab built?
OKLab wasn't born out of a standards body, but out of one person's work. The Swedish software developer Björn Ottosson published a post titled "A perceptual color space for image processing" on his personal site on December 23, 2020, introducing OKLab.
Ottosson lists the shortcomings of existing spaces explicitly: CIELAB and CIELUV don't predict hue well, with blues predicted particularly poorly; CAM16-UCS is generally uniform but has problematic numerical behavior and doesn't blend colors smoothly; an older space called IPT predicts hue well but doesn't predict lightness and chroma well. His goal was a space that combined the good parts of these, was simple, and was numerically stable.
The method was this. OKLab was built as a space with the same structure as IPT: linear light values are first converted by a matrix into values resembling the three cone responses, a cube root is applied to these, and a second matrix converts them into lightness and two opponent color axes. The coefficients of the two matrices were determined by an optimization: to best fit color pairs of constant lightness and constant chroma generated with CAM16, and the smooth hue data from IPT research. In other words, OKLab mimics CAM16 for lightness and chroma, and IPT for hue.
Part of OKLab's success lies in its simplicity: two matrices and a cube root can be written in a few lines in any programming language, and reversed. Its white point is D65, the standard white of screens, which makes it easy to work with screen spaces like sRGB and Display P3.
Spaces for high dynamic range
CIELAB and OKLab are designed for standard dynamic range, meaning cases where white is roughly a sheet of paper's or a screen's white. High-dynamic-range images, HDR for short, can show much darker shadows and much brighter highlights in detail, a glint of metal reflecting the sun, or a lamp itself. Across this range, a simple compression like a cube root doesn't represent the eye's behavior well.
For HDR television, the ITU's BT.2100 recommendation defines two transfer functions for encoding the signal. One of these, also defined in the SMPTE ST 2084 standard, is the Perceptual Quantizer, designed around the smallest steps the eye can tell apart at different brightness levels, PQ for short.
The same recommendation also defines a color representation: ICtCp. In this representation, the I component carries intensity, and the Ct and Cp components carry two opponent color axes. Its most important advantage over television and video's older YCbCr representation is that it separates brightness information from color information better; operations like compressing the color components or mapping out-of-gamut colors distort brightness less. ICtCp isn't a design tool; it's an engineering representation developed for encoding and processing HDR video signals.
As a perceptual space aimed at HDR, one of the most frequently cited proposals is Jzazbz. In a paper published in Optics Express in 2017, Muhammad Safdar, Guihua Cui, Youn Jin Kim, and Ming Ronnier Luo proposed a color space intended to correspond to perception in equal steps for image signals with high dynamic range and wide gamut. Jzazbz uses a lightness and two opponent axes, similar in structure to CIELAB, but it's designed to behave uniformly over a much wider brightness range.
A rough division of labor can be drawn: OKLab stands out for interface, gradient, and image-editing work in standard dynamic range; ICtCp for encoding and processing HDR video signals; and Jzazbz for research into color differences and color editing in HDR and wide-gamut content. This division isn't fixed; the fields keep developing.
Entering web standards
The place where OKLab spread fastest was the web. The W3C's CSS Color Module Level 4 specification defines writing colors in OKLab and OKLCh alongside CIELAB and its polar form, LCH. The specification's Candidate Recommendation Draft, dated September 13, 2026, also sets an important rule for interpolation: if the space for color interpolation isn't specified where it's used, the default space is OKLab.
The same specification also recognizes an exception: interpolation between colors written in hex codes, color names, and older sRGB formats like rgb(), hsl(), and hwb() is still carried out by browsers in gamma-encoded sRGB space, so that the appearance of existing pages on the web isn't broken. That means a blue-yellow gradient defined with the old syntax still falls to gray in the middle today; a designer gets a better result either by writing one of the colors in the new format or by explicitly specifying the interpolation space.
How this syntax is used in practice, browser support, and fallback methods for wide-gamut colors are the subject of UX-09. What matters here is the theoretical point: a perceptual space went from a research post to becoming, within a few years, the default of the world's most widely used software platform.
Limits: what OKLab is not
OKLab's popularity has started to make it look like some kind of "correct color space." This is misleading.
First, OKLab is not a color appearance model. It doesn't account for ambient light, the lightness of the background, how bright the image is displayed, or the eye's state of adaptation; the models that do this are the subject of BI-22. OKLab works under the assumption of "normal viewing conditions" and with D65 white.
Second, OKLab was built by fitting itself to other models. Its lightness and chroma behavior rests on data generated from CAM16, its hue behavior on IPT data; that is, it was derived not directly from a new perception experiment but from the data of existing models. This doesn't make it bad, but it ties its accuracy to the accuracy of those models.
Third, not every color calculated in OKLab can be shown on screen. Raising the chroma or blending two distant colors can push the result outside the screen's gamut; the color then has to be converted into one that can be shown. CSS Color 4 adopts the same principle in all three gamut-mapping algorithms it defines for this: holding lightness and hue constant in OkLCh space and reducing chroma. If lightness is equal to or greater than 1, the result is white; if it's equal to or less than 0, it's black. This choice is a consequence of the trust placed in OKLab's hue linearity: it's assumed that hue won't drift as chroma is reduced. The gamut-mapping methods themselves, and the choice between them, are the subject of EK-14.
Fourth, perceptual uniformity is a relative concept. For measuring color differences, industry still uses CIELAB-based formulas, especially CIEDE2000; these are explained in BI-20. A straight-line distance in OKLab doesn't replace these formulas.
Example — a skin tone scale
An app team is preparing a skin tone scale running from light to dark for users' avatars. They put two colors at the ends: a pinkish skin color at the lightest end (#F1C7A9) and a very dark, warm brown tone (#4A2C1D). They plan to generate the tones in between with a gradient and are debating which space to use.
The calculation gives a surprising result. The midtone interpolated in sRGB is #9E7A63, and the one interpolated in OKLab is #9A755F; on the OKLab scale their lightness values are 0.61 and 0.59, their hue angles are 53° and 53°, and their chroma values are 0.056 and 0.057. The difference is this small at the quarter and three-quarter points too. The two ends belong to the same hue family and have low chroma; the path between them doesn't pass through the neutral axis or the purple region. In this case, the choice of space changes almost nothing.
The lesson here is this: OKLab's advantage shows up in gradients whose ends are far apart, complementary, or pass through the blue region. In a skin scale, the real decisions lie elsewhere: whether the ends truly represent different skin tones, whether the steps look equal in lightness, and whether the scale is a single line that only changes lightness or a family that also covers different undertones, for example more yellowish or more reddish skin. A single straight line assumes that every skin tone between light and dark shares the same undertone. Real skin diversity isn't a line, though, it's an area.
Common misconception
Common mistake"Once you interpolate in OKLab, gray never appears between complementary colors."
OKLab removes false darkness and hue shifts, but in a space with opponent axes, the straight line joining two complementary colors still passes close to the neutral axis; preserving colorfulness requires interpolating along the hue circle in OKLCh.
Common mistake"OKLab has replaced CIELAB for every job."
OKLab is spreading in interfaces, gradients, and image processing; but industrial color measurement, tolerance, and quality control are still built on CIELAB and CIEDE2000, and OKLab is not a color appearance model.
Summary
- CIELAB's hue linearity isn't complete; especially in blues, hue drifts as lightness or chroma changes, and a transition from blue to white veers toward purple.
- Interpolation done in gamma-encoded sRGB leads to a dark gray between complementary colors and to muddy intermediate tones in other pairs; OKLab keeps the midpoint at the perceptual average lightness and removes false hue shifts, while OKLCh also preserves colorfulness by traveling around the circle.
- Representations like PQ, ICtCp, and Jzazbz were developed for HDR to account for a much wider brightness range; OKLab, meanwhile, became the default interpolation space on the web, but it's not a color appearance model, and older sRGB syntaxes are still blended in sRGB.
Test yourself
- (Easy) Who proposed OKLab, and when?
- (Easy) In which standard is ICtCp defined, and for what purpose is it used?
- (Medium) Why does a gradient turn gray in the middle, and how does OKLab solve it?
- (Medium) What did Hung and Berns's study show about CIELAB?
- (Hard) Why is a gradient between two colors written in the old format still calculated in sRGB in CSS today, and how can a designer change this?
- (Hard) Why did the choice of space change almost nothing in the skin tone scale example, and what does this say about the limit of OKLab's advantage?
Answers
- The Swedish software developer Björn Ottosson, with a post he published on his personal site on December 23, 2020 ("How was OKLab built?").
- In ITU-R BT.2100; as a representation for encoding and processing high-dynamic-range video signals that separates brightness from color information better than the older YCbCr does ("Spaces for high dynamic range").
- Interpolation is usually done with gamma-encoded sRGB values; the average of these values is neither the physical average nor the perceptual average, and the exact midpoint of complementary blue and yellow falls to a dark gray like #808080. OKLab keeps the midpoint at the perceptual lightness average of the two ends and prevents false hue shifts; to also preserve colorfulness between complementary colors, interpolation is done in OKLCh, along the hue circle ("The gradient question: why does the middle turn gray?").
- That the perceived hue drifts as you move along a fixed hue angle from neutral toward the highest chroma, and that the largest errors fall in the region of the screen's blue primary ("Why wasn't CIELAB enough?").
- CSS Color 4 requires that interpolation between hex codes, color names, and older formats like rgb(), hsl(), and hwb() be done in gamma-encoded sRGB so existing pages aren't broken. A designer can move to a space like Oklab either by writing at least one of the colors in the new format or by explicitly specifying the interpolation space ("Entering web standards").
- The two ends belonged to the same hue family and had low chroma; because the path between them didn't pass through the neutral axis or the blue-purple region, sRGB and OKLab gave almost the same intermediate tones. OKLab's advantage shows up in transitions whose ends are far apart, complementary, or pass through the blue region; in a skin scale, the real decisions are the choice of the ends, the steps, and the range of undertones ("Example — a skin tone scale").
Sources
- Hung, P.-C., and Berns, R. S., "Determination of constant hue loci for a CRT gamut and their predictions using color appearance spaces," Color Research and Application 20(5): 285–295, 1995.
- Ottosson, B., "A perceptual color space for image processing," personal blog, December 23, 2020.
- Safdar, M., Cui, G., Kim, Y. J., and Luo, M. R., "Perceptually uniform color space for image signals including high dynamic range and wide gamut," Optics Express 25(13): 15131–15151, 2017.
- ITU-R, "Recommendation BT.2100-3: Image parameter values for high dynamic range television for use in production and international programme exchange," February 2025.
- W3C, "CSS Color Module Level 4," Candidate Recommendation Draft, September 13, 2026.
Next step
UX-09 carries this lesson's theory into the browser: it covers, hands-on, the oklch() and color-mix() functions, relative color syntax, Display P3 colors, and fallback methods for screens that don't support them. BI-22, meanwhile, turns to what OKLab deliberately leaves out: it explains how color appearance models like CIECAM02 and CAM16 account for ambient light, background, and brightness level, and the difference between brightness, saturation, and colorfulness.