color theory

sRGB

sRGB is the color space behind every hex code you have ever used. Released in 1996 by Microsoft and HP it standardized RGB values for the web using primaries from BT.709 a D65 white point and a gamma of roughly 2.2 to match CRT monitors of the day. It turned chaotic color reproduction into something predictable. #4A90E2 means the same thing on every sRGB calibrated screen. CSS uses it as the default for rgb() hex and hsl() functions. For its original purpose of making colors consistent across 1990s hardware it was a success. Design tools from early Photoshop to current Figma still default to it. Browsers assume sRGB unless you specify a different color space. It solved a real problem in the dial up era when monitors varied wildly. Without sRGB the early web would have been an even bigger mess of inconsistent colors across devices.

sRGB is not perceptually uniform. It was never designed to be. Its coordinate system does not match human vision. Equal steps in sRGB do not look equal to the eye. The lightness it provides is not the same as perceived brightness. Blue at any given value looks darker than yellow at the same value. This creates lightness drift across your palette that forces manual overrides in dark mode and breaks contrast predictions. HSL tried to paper over the issue with friendlier names but it still maps back to sRGB so the problems remain. Gradients in sRGB travel through muddy paths because they follow the RGB color cube instead of perceptual reality. The gamut is tiny covering only colors available on old monitors and leaving out the vivid range of modern P3 displays that Apple has shipped since 2016. It assumes viewing conditions that no longer match how we use screens in 2025. OKLCH was built in 2020 by Björn Ottosson to solve exactly these flaws with true perceptual lightness and sane hue interpolation. The fact that we needed a new space thirty years later shows how mismatched sRGB was for design work all along.

Concrete example. Open your dev tools and compare these two colors that designers often treat as equivalent in sRGB based systems. First #2563EB a typical blue 500. Second #EA8A0C a typical amber 500. In most palettes these sit at the same visual level. Yet the blue has an approximate relative luminance of 0.18 while the amber sits at 0.55. That difference means they never behave the same in contrast calculations or dark mode. In the OKLCH ramp shown in the parent article both would share an L value of 0.54 making them true visual equals for the first time. The article mentions how blue 500 in most systems looks darker than yellow 500 even when they share the same relative position in the ramp. That is not a taste problem. It is a math problem baked into sRGB. This exact issue bit the Tailwind team before version 4. Their old sRGB based blues always looked heavier than their yellows at the same stop. Designers at Shopify ran into the same problem with Polaris in 2022 spending days adjusting individual hex values to make the palette feel balanced. Another concrete example is the blue to yellow gradient. In sRGB linear gradient from hsl(217 91% 60%) to hsl(45 100% 51%) passes through a disgusting gray brown in the center. The interpolation follows the straight line through the RGB cube hitting low chroma near the middle. In OKLCH the same gradient stays clean and arcs through teal and green the way your brain expects color to transition. These are not theoretical issues. They are the daily reality for any team still building palettes in hex. Google hit the same walls in Material Design 2 before overhauling their system with more perceptual adjustments in Material 3.

Use sRGB as a fallback. Always declare your hex value first in CSS then follow with the OKLCH equivalent. This ensures the 7 percent of users on older browsers still get a decent experience. Use it when a brand guide from 2015 specifies exact hex values that marketing refuses to update. It works for quick mocks email campaigns static assets and any situation where you need one number that every tool understands instantly. sRGB remains the lowest common denominator for color on the web and the safe first line in every custom property.

Do not use sRGB to define your primitive color scales in a modern design system. Do not pick colors by tweaking values in Figma default color picker. Do not generate 11 step ramps by hand adjusting hex until they look right. That approach guarantees lightness drift that will haunt your dark mode your contrast ratios and your component states. Do not create gradients or transitions directly in it. The muddy middles are inevitable. Companies like Linear switched to OKLCH in 2024 and eliminated dozens of contrast bugs in one move. Stripe did the same for their new design language. Apple has been pushing P3 since 2016 because sRGB cannot even name the saturated colors their hardware can display. The four step migration in the parent article starts with an audit of your existing sRGB palette. The bugs jump out immediately when you sort by OKLCH L value. Blue at 0.72 while yellow at 0.87 for the same nominal step. That audit alone justifies the switch. If your team is still having arguments about why the blue feels heavier than the orange at the same step then sRGB is the reason. Treat it as an output format only. Do your thinking in OKLCH. Generate the system there. Output sRGB only for legacy support. The migration takes days but removes years of accumulated technical debt in your color tokens.

sRGB built the web we knew but OKLCH builds the web we actually see.

Related terms

Keep exploring