Color Picker

Formats

HEX
#9a4b24
RGB
rgb(154, 75, 36)
HSL
hsl(20, 62.1%, 37.3%)
HSV
hsv(20, 76.6%, 60.4%)
OKLCH
oklch(0.505 0.1177 44.82)
CMYK
cmyk(0%, 51.3%, 76.6%, 39.6%)

Contrast

Aa6.17:1AA pass
Aa3.41:1Large text only

Lightness scale

  • #ffd5ac
  • #ffb189
  • #e38d66
  • #bd6b45
  • #984a22
  • #742900
  • #520300
  • #2f0000
  • #0d0000

Nothing you enter here is stored, logged or shared.

Pick a color and read it in every common format, including OKLCH, with live WCAG contrast ratios against white and black.

How to use

  1. Drag on the panel, or paste a hex, rgb() or hsl() value.
  2. Copy whichever format you need.
  3. Check the contrast ratios before using it for text.

The formats, and when each is the right one

Hex and rgb() are the same thing written differently: three channel values as the display will drive them. They are exact and universally understood, and they tell you nothing about how a color will look next to another one.

hsl() rearranges the same information into hue, saturation and lightness, which is easier to reason about - rotate the hue, keep the rest - and is why it became the default way to build palettes in CSS. hsv() is the sibling used by most graphics applications' color pickers.

oklch() is the one worth learning if you do not already know it. cmyk() is included for reference and should be treated as approximate, because a real conversion depends on the ink, the paper and the output profile; the value here is the standard arithmetic formula, useful for a rough idea and not for sending to a press.

Why OKLCH is different

HSL's lightness is a geometric average of the channels, not a measure of how bright a color looks. Pure yellow and pure blue both sit at 50% lightness in HSL, and one of them is nearly white to the eye while the other is nearly black. Every palette built by holding HSL lightness constant therefore comes out uneven, and gets hand-corrected color by color until it looks right.

OKLCH is built on the Oklab perceptual space, where equal numeric steps correspond to roughly equal perceived differences. Hold lightness constant across hues and the colors genuinely look equally light; step it evenly and you get an even scale. This is what makes it useful for generating tints and shades, for building accessible pairs, and for interpolating between two colors without the muddy grey that appears halfway through an RGB blend.

One caveat: OKLCH can describe colors outside the sRGB gamut, and those get clipped when displayed on an ordinary screen. High chroma at extreme lightness is where this shows up, and the effect is that two different OKLCH values render identically.

Reading the contrast ratios

Contrast is computed with the WCAG 2 formula: relative luminance for each color with the sRGB channels linearised, then the lighter plus 0.05 over the darker plus 0.05. The result runs from 1 to 1 for two identical colors up to 21 to 1 for black on white.

The thresholds are 4.5 to 1 for normal body text at AA, 3 to 1 for large text - roughly 24px, or 19px bold - and for interface components and meaningful graphics, and 7 to 1 for AAA. Ratios against both white and black are shown because which one you need depends on which the color is sitting on, and a color that fails on white often passes comfortably on black.

The formula has known weaknesses and it is worth not treating the number as the whole answer. It systematically overstates contrast for light text on dark backgrounds, which is why some dark themes that pass on paper are uncomfortable to read, and it takes no account of font weight or size beyond the single large-text threshold, so hairline weights that pass can still be hard work. A successor metric, APCA, addresses both and is not yet what the guidelines require. Meet the ratio, then look at it.

Alpha, and the eight-digit hex

Hex can carry alpha as a fourth channel: #RRGGBBAA in full, or #RGBA in shorthand. Both are supported by every current browser, and both are accepted here.

Two things go wrong with them. The first is channel order - some platforms, Android among them, write the alpha first as #AARRGGBB, so a value copied out of one of those tools and pasted into CSS produces a confidently wrong color rather than an error. The second is that the alpha is hexadecimal, so 50% opacity is 80 rather than 50; the modern rgb(0 0 0 / 50%) syntax avoids the arithmetic entirely and is easier to read six months later.

What a colour value actually describes

A hex triplet is not a colour, it is an instruction to a display. #CC0000 says to drive the red channel at 80% of its maximum and the others at zero, and what a viewer sees depends on the panel, its calibration, the ambient light and the colour space the number is interpreted in.

That colour space is sRGB unless something says otherwise. It was standardised in 1996 to describe the CRT monitors of the day, and it stuck because the web needed one assumption everyone could share. Modern phone and laptop screens cover a wider range than sRGB, which is why an image tagged Display P3 looks more saturated than the same numbers interpreted as sRGB.

One more subtlety hides in the numbers: sRGB is not linear. The value 128 is not half as bright as 255, because the encoding has a gamma curve that allocates more precision to dark tones, where human vision is more sensitive. This is why averaging two hex values channel by channel gives a muddier result than blending the same colours in a linear space, and why contrast formulas linearise the channels before doing any arithmetic.

Building a usable palette from one colour

Most interface palettes are a handful of hues each expressed at several lightness steps: a background, a subtle surface, a border, a muted text colour, a solid brand colour, and one or two darker shades for hover and active states. Nine to eleven steps per hue is a common choice because it covers light and dark themes from one definition.

The method that works is to fix the perceptual lightness of each step across every hue, then let chroma vary. Step 500 of the blue, the green and the red should read as equally heavy on the page; if one jumps out, the scale will look unbalanced everywhere it is used. Doing this in OKLCH means the numbers do the work; doing it in HSL means correcting each colour by eye.

Chroma usually has to taper at the extremes. Very light and very dark colours cannot hold much saturation inside the sRGB gamut, so a scale that keeps chroma constant will clip at both ends, and two adjacent steps will render identically.

Colour is not the only channel

Around one in twelve men and one in two hundred women has some form of colour vision deficiency, most commonly a reduced ability to distinguish red from green. A status system built on red and green alone is invisible to them, and the same is true for a chart whose series differ only by hue.

The fix is redundancy rather than avoidance: pair colour with a shape, an icon, a label or a position. A red error message with an exclamation icon and the word Error works for everyone; the red alone works for most people. For charts, direct labels beat a legend, and varying lightness as well as hue keeps a series distinguishable when the page is printed in greyscale.

Contrast ratios matter here too, and they are cheap to check. Text at 4.5 to 1 and interface elements at 3 to 1 are the thresholds most procurement rules and accessibility audits use.

Dark themes are not an inversion

Flipping every colour produces a dark theme that feels wrong, for reasons that are mostly perceptual. Light text on a dark background appears to bloom and read heavier, so the same weight looks bolder; saturated colours vibrate against dark surfaces; and pure black with pure white text produces a halo effect that makes body copy tiring.

The usual adjustments are to use a very dark grey rather than black, to reduce saturation in the accent colours, to lean on lighter surfaces rather than shadows for elevation since a shadow is invisible on black, and to reduce font weight slightly rather than matching the light theme exactly.

Both themes need checking independently. A colour that passes contrast on white frequently fails on a dark surface and vice versa, which is why the ratios here are shown against both at once.

Colour in CSS, and how to organise it

Modern CSS accepts all of these formats directly, including oklch() and the space-separated syntax with a slash for alpha: rgb(0 0 0 / 50%). That syntax is worth adopting because it reads unambiguously and because the alpha is a percentage rather than a hexadecimal pair nobody can convert in their head.

The durable way to organise colour is two layers of custom properties. The first layer names the palette literally - --blue-500, --grey-900 - and the second names the role: --color-text, --color-surface, --color-border, --color-accent. Components reference roles only, which means a dark theme is a redefinition of the role layer rather than an edit to every component.

Two newer features change what is possible. color-mix() blends two colours at a stated ratio in a stated space, so a hover state can be derived from a base colour rather than hand-picked. And relative colour syntax lets you build a variant from an existing value by adjusting one channel, which keeps a scale in sync with the colour it was derived from. Both are supported across current browsers, and both are far easier to reason about in OKLCH than in HSL.

Frequently asked questions

What is OKLCH and why use it over HSL?
OKLCH is a perceptual color space: equal steps in lightness look equally different to the eye, which HSL does not manage. Two HSL colors with the same lightness value can look wildly different in brightness, so palettes built in HSL need constant hand-correction. OKLCH is supported in all current browsers and is the better basis for scales and accessible pairs.
How is the contrast ratio calculated?
Using the WCAG 2 formula, from relative luminance with the sRGB channels linearised. A ratio of at least 4.5 to 1 passes AA for normal text, 3 to 1 for large text and interface components, and 7 to 1 passes AAA.
Why does the CMYK value not match my print software?
Because real CMYK conversion depends on the output profile, the ink and the paper. The value here is the standard arithmetic approximation, which is fine for reference but should not be sent to a press without checking against your own profile.
What formats can I paste in?
Hex in 3, 4, 6 or 8 digits, with or without the hash, plus rgb(), rgba(), hsl() and hsla() including the modern slash-separated alpha syntax.
How is the lightness scale generated?
By holding chroma and hue constant in OKLCH and stepping the lightness. Doing this in HSL produces steps that look uneven and often muddy in the middle.

Last updated:

Report a problem

Include the steps, expected result, and actual result. Remove secrets and personal data.

Related tools