How to Use the Color Converter
Use the color picker or enter a color value to convert. Supports HEX, RGB, HSL, HWB, LAB, LCH, OKLAB, OKLCH, CSS Color Names, and CSS Color Functions as input values. The tool will parse it and convert it to all the supported notations.
The three main color spaces shown are sRGB (Hex, RGB, HSL, HWB), CIELAB (Lab, LCH), and OKLab (OKLab, OKLCH). You can copy individual values or grab a full set of CSS Custom Properties to use in your project.
The alpha slider lets you preview transparency independently of whatever alpha value you typed, and the eyedropper button (in browsers that support it) lets you sample a color directly from anything on your screen, not just the page. The native color picker stays in sync when the current color is fully opaque and fits inside sRGB, since that's the only situation it can represent exactly.
If you want to grab everything at once, the "Copy All as CSS Variables" button copies a ready-to-paste :root block with the current color written in all eight standard notations, which can be handy when you're documenting a design token or comparing formats side by side. It's limited to those eight on purpose, since a block with the wide-gamut and linear formats included as well would be long enough to defeat the point.
The wide-gamut and linear formats work the same way in reverse. Paste in a color(display-p3 ...), color(rec2020 ...), or any other supported color() value, and the tool parses it, converts it to the shared internal color, and updates every card, standard and advanced alike.
How the Tool Works
Everything runs in your browser. There's no server call and nothing gets logged anywhere. When you type or paste a color, the tool parses it against the CSS Color Module 4 syntax for each notation, converts it into a shared internal color, and then formats that internal color back out into all the others using the standard conversion matrices for sRGB, CIE Lab, and OKLab.
Examples
Converting a color from one notation to another is only half the point. The other half is knowing which notation actually solves the problem in front of you. These are a few situations where picking the right one makes a real difference.
Same Color, Three Ways
These three lines all paint the exact same blue. Which one you reach for usually comes down to habit and what the rest of your codebase already uses:
background: #3498db;
background: rgb(52 152 219);
background: hsl(204deg 70% 53%);
Smoother Gradients With OKLCH
Browsers interpolate a gradient in whatever color space it's told to, and the default is a legacy space that can produce a dull, grayish band through the middle of a gradient between two saturated colors. Adding an in oklch hint tells the browser to interpolate in a space built for this, which keeps the transition looking vivid the whole way through:
/* Default interpolation can look muddy in the middle */
background: linear-gradient(90deg, #ff0066, #0066ff);
/* Interpolating in OKLCH keeps it vivid */
background: linear-gradient(in oklch 90deg, #ff0066, #0066ff);
This works the same way for radial-gradient() and conic-gradient(), and it's supported in every current major browser.
There's a shortcut worth knowing here. The legacy sRGB default only applies when every color stop is written in a legacy format, meaning hex, a named color, rgb(), hsl(), or hwb(). Write the stops in oklch() instead and the browser interpolates in Oklab automatically, no hint required:
/* No "in oklch" needed, the oklch() stops trigger it by default */
background: linear-gradient(90deg, oklch(0.65 0.25 010), oklch(0.65 0.25 250));
The two approaches land in the same place. Which one to use is mostly about what's already in your stylesheet: if you're already working in hex or RGB for a specific reason, add the in oklch hint. If you're starting fresh or converting the stops anyway, writing them as oklch() gets you the same result with less to type.
Transparent Overlays
Alpha values are where rgb() and hsl() tend to earn their keep, since it's easy to eyeball a percentage and know roughly how see-through something will be:
.modal-backdrop {
background: rgb(0 0 0 / 55%);
}
.tooltip {
background: hsl(220deg 20% 12% / 92%);
}
Hover States Without a Second Color
Relative color syntax lets you derive a new color from an existing one right inside CSS, instead of hand-picking a second hex value and hoping it reads as "the same color, but darker." This example takes a brand color and darkens it for a hover state by pulling the lightness channel down while leaving chroma and hue untouched:
:root {
--brand: oklch(0.6 0.18 250);
}
.button {
background: var(--brand);
}
.button:hover {
background: oklch(from var(--brand) calc(l - 0.08) c h);
}
Because OKLCH separates lightness from hue and chroma, dropping the lightness value alone darkens the color without also dulling or shifting it, which is a common problem when you try the same trick in hex or RGB.
Tints and Shades From One Base Color
Design systems often need a full ramp of a single brand color, from a pale background tint to a deep shade for text. Doing this in OKLCH by holding hue and chroma steady and sliding only lightness produces a much more even, predictable ramp than nudging RGB or hex values by feel:
:root {
--brand-10: oklch(0.96 0.02 250);
--brand-30: oklch(0.82 0.08 250);
--brand-50: oklch(0.6 0.18 250);
--brand-70: oklch(0.42 0.16 250);
--brand-90: oklch(0.22 0.1 250);
}
Run each of these through the converter above if you want to see what they look like in hex or RGB too, or to check whether any of them fall outside sRGB.
What Are CSS Color Notations?
Every color on the web ends up as light from a screen, but CSS gives you a handful of different ways to describe that light in code. Hex codes and rgb() are the ones most developers learn first. hsl() and hwb() describe color the way a person might, in terms of hue and how light or saturated it is. Then there's a newer set, lab(), lch(), oklab(), and oklch(), which are based on how human vision actually perceives color rather than how a screen produces it.
None of these notations are wrong. They're different tools for different jobs, and the converter above lets you paste in a color in any of them and immediately see the same color written every other way, including the closest named CSS color if one happens to match exactly.
Hex and RGB
Hex codes like #3498db pack red, green, and blue values into pairs of characters, each running from 00 to ff. They're compact and everywhere, from design tools to old-school HTML attributes, which is why they've stuck around since the early web. rgb() is the same idea spelled out, with the added option of writing an alpha channel for transparency, like rgb(52 152 219 / 50%).
The catch with both is that they're tied directly to how a monitor mixes red, green, and blue light. Halfway between two hex values isn't necessarily what a person would call the halfway point between two colors, which matters more than it sounds like once you start building gradients or animating between colors.
HSL and HWB
HSL was designed to match how people actually talk about color. A hue from 0 to 360 degrees picks the base color, saturation controls how vivid it is, and lightness slides from black to white. It's the notation most developers tend to use when they want to nudge a color lighter or darker without doing math, since bumping the lightness value does exactly what it says.
HWB works from the same hue wheel but mixes in whiteness and blackness instead of saturation and lightness. Push the whiteness up and the color pales toward white, push the blackness up and it darkens toward black. It's less common than HSL but genuinely useful when you're thinking in terms of tinting and shading a base hue, which is a normal way for designers to reason about a palette.
Lab, LCH, OKLab, and OKLCH
Lab and LCH come from a color model built in the 1970s to match human perception rather than a specific screen technology. The L axis is lightness, and instead of red, green, and blue channels, Lab uses two axes (labeled a and b) that run from green to red and blue to yellow. LCH takes the same space and rewrites it in terms of lightness, chroma (how intense the color is), and hue, which tends to be easier to reason about by hand.
OKLab and OKLCH are a more recent refinement of the same idea, tuned to fix some perceptual quirks in the original Lab model. Practically, this means that equal steps in OKLCH's lightness or chroma values look like equal steps to the eye, which makes it a strong choice for building color scales, gradients, or anything where a color needs to shift smoothly. Both Lab-based and OKLab-based formats can also describe colors outside what a typical monitor can display, which is why the converter above flags a card as clipped when a wide-gamut color has to be squeezed into sRGB for hex, RGB, HSL, or HWB.
Wide-Gamut and Linear Color Spaces
Every notation covered so far describes a color as your monitor would mix it, within the boundaries of sRGB, which is the color space most screens have targeted for the last thirty years. Newer displays can go further, and CSS has a way to reach them: the color() function, which lets you name a specific color space and hand it raw component values. The converter's "Wide-Gamut & Linear Notations" heading further down the page shows the current color in each of these.
Display P3 is the one you're most likely to actually use. It's the color space Apple's displays have shipped with for years and is now common on high-end monitors and phones generally, covering a noticeably wider range of greens and reds than sRGB can reach. A photo or illustration meant to look as vivid as the source file, rather than clipped down to sRGB, often gets exported for the web in color(display-p3 ...).
A98 RGB (Adobe RGB) and Rec. 2020 are two more RGB-based spaces you'll run into outside pure web work. A98 RGB has been a print and photography standard since the 1990s, with better coverage of cyans and greens than sRGB. Rec. 2020 is the color space behind 4K and 8K broadcast video and covers a gamut wider than either sRGB or Display P3, though very few consumer displays can reproduce all of it yet.
ProPhoto RGB goes further still, covering a gamut so wide that a meaningful slice of it doesn't correspond to colors human vision can actually perceive. It shows up mainly in high-end photography workflows as a working space for editing, not as a space anything gets displayed in directly.
Linear sRGB is sRGB's own gamut with the gamma curve removed, so the numbers represent light intensity directly rather than the perceptually-adjusted values sRGB and Display P3 normally use. It's mostly useful for calculations, like lighting or blending math, where working with actual light values instead of gamma-encoded ones avoids some subtle errors.
XYZ is the oldest color space of the group and sits underneath all the others. Instead of red, green, and blue, it uses three values (X, Y, and Z) derived directly from how the human eye's cone cells respond to light, which makes it the common reference every other space gets converted through. You'll rarely write CSS in XYZ directly, but it's worth knowing it's there since every conversion this tool performs passes through it internally. CSS defines two versions depending on which reference white point is used, D65 (the same one sRGB and Display P3 use) and D50 (used by Lab, LCH, and ProPhoto RGB); the plain color(xyz ...) keyword is shorthand for color(xyz-d65 ...).
Unlike hex, RGB, HSL, and HWB, none of these formats get silently clamped by the converter, since a value like color(display-p3 1.05 0 0) is valid CSS on its own terms and it's up to the browser to map it into whatever the screen can actually show.