Color Converter & Contrast Checker

Convert a color between HEX, RGB, HSL and OKLCH, and check two colors against WCAG.

Every format

FormatValueCopy
HEX#336699
RGBrgb(51 102 153)
HSLhsl(210 50% 40%)
OKLCHoklch(49.93% 0.0987 250.43)

Contrast

The quick brown fox jumps over the lazy dog.

6.00:1

  • PassAA, normal text needs 4.5:1
  • PassAA, large text needs 3:1
  • FailAAA, normal text needs 7:1
  • PassAAA, large text needs 4.5:1

Runs in your browser. Nothing you enter is sent anywhere.

How to use it

Type into Color: a hex code, rgb(), hsl(), oklch() or one of the 148 CSS color names. The chips under it load samples. The swatch and the Every format table update as you type, worked out in the page, and each row (HEX, RGB, HSL, OKLCH) has its own copy button.

  1. To check contrast, enter a second color in Check against. It starts as #ffffff; clear it to skip the check.
  2. Contrast shows a sample sentence in the first color on the second, the ratio, and four lines reading Pass or Fail: AA and AAA, each for normal and large text.

If the text can’t be read, a message above the table says what’s wrong, and the table keeps the last color that parsed.

Examples

The page’s starting pair, #336699 with Check against set to #ffffff:

HEX    #336699
RGB    rgb(51 102 153)
HSL    hsl(210 50% 40%)
OKLCH  oklch(49.93% 0.0987 250.43)
6.00:1
Pass  AA, normal text   needs 4.5:1
Pass  AA, large text    needs 3:1
Fail  AAA, normal text  needs 7:1
Pass  AAA, large text   needs 4.5:1

Swap the boxes and it’s still 6.00:1: the lighter color always goes on top.

A gray right at the line, #767776 on #ffffff, shows 4.50:1, yet AA normal and AAA large fail, with the note That number is rounded. The exact ratio is just under 4.5, so the two checks that ask for 4.5:1 fail. WCAG’s thresholds are exact, so rounding up doesn’t count.

An OKLCH color outside sRGB, oklch(0.7 0.3 145):

HEX    #00bf34
RGB    rgb(0 191 52)
HSL    hsl(136.4 100% 37.5%)
OKLCH  oklch(70% 0.2202 145)

The note under the table reads sRGB can't show that color. Its chroma was reduced from 0.3 to 0.2202 to bring it in, rather than clamping the channels, which would have shifted the hue. Lightness and hue stay at 70% and 145.

A hex code one digit short, #ff573, is rejected with A hex color has 3, 4, 6 or 8 digits: "#ff573" has 5.

Good to know

  • Four- and eight-digit hex carry alpha. CSS Color 4 reads #rgba and #rrggbbaa, so #ff57 isn’t a short #ff5733: it’s #ffff5577, a yellow at 0.467 opacity.
  • Output uses the modern syntax, space-separated with alpha after a slash: rgb(0 0 0 / 0.5). Input may also use the legacy comma form, rgba(0, 0, 0, 0.5).
  • HSL needs percent signs here. hsl(210 50 40) is rejected; write hsl(210 50% 40%). Hue is in degrees, with or without deg, and wraps: hsl(400 50% 50%) comes out as hsl(40 50% 50%).
  • OKLCH lightness runs 0 to 1 or 0% to 100%. Chroma starts at 0, and 100% means 0.4, as in CSS Color 4. A gray has no hue, so zero chroma shows hue 0.
  • Every row comes from the exact color, not the rounded hex. Hex and RGB round each channel to 8 bits, so pasting the hex back can move the last digits: #00bf34 reads oklch(69.93% 0.2202 144.97).
  • WCAG contrast is a luminance ratio. Relative luminance weights the linearized sRGB channels 0.2126, 0.7152 and 0.0722; the ratio is (L1 + 0.05) / (L2 + 0.05), from 1:1 to 21:1. Large text is at least 18pt (24px), or 14pt (about 18.7px) bold.
  • Translucent colors are flattened first. The background is laid over a white page and the foreground over that, then the result is measured: rgb(0 0 0 / 50%) on #ffffff gives 3.98:1, the ratio of the mid gray you see.
  • Not read: transparent, currentcolor, lab(), lch(), oklab(), hwb(), color(), none and numbers like 1e2. Each box holds up to 120 characters.

Questions

How do I convert hex to RGB?

Read each pair of digits as a base-16 number: in #ff5733, ff is 255, 57 is 87 and 33 is 51, so it’s rgb(255 87 51). A three-digit code doubles each digit first, so #f53 is #ff5533. In JavaScript, parseInt('57', 16) returns 87.

How do I convert RGB to hex?

Write each channel from 0 to 255 as two hex digits and join them: 51, 102 and 153 become #336699. In JavaScript, n.toString(16).padStart(2, '0') does one channel. A percentage is multiplied by 255 and rounded first, so rgb(100% 50% 0%) is #ff8000.

What contrast ratio does WCAG require?

At level AA, 4.5:1 for normal text and 3:1 for large text (success criterion 1.4.3); at AAA, 7:1 and 4.5:1 (1.4.6). Icons and the parts that identify a control, such as a text field’s border, need 3:1 against adjacent colors (1.4.11). Logos and disabled controls are exempt.

What is OKLCH, and why use it instead of HSL?

OKLCH is the polar form of OKLab, a perceptual color space Björn Ottosson published in 2020: lightness, chroma and hue angle. Its lightness tracks what the eye sees, and HSL’s doesn’t: hsl(60 100% 50%) and hsl(240 100% 50%) share 50% lightness but convert to oklch(96.8% 0.211 109.77) and oklch(45.2% 0.3132 264.05). All current major browsers support oklch().