Digitopia Labs

Tints and shades

Build a tint and shade ramp from one colour, with the contrast ratio each step actually achieves against white and black. Free, no sign-up.

Build a ramp

Hex, rgb(), hsl() or oklch(). Nothing is sent anywhere.

  1. Step 50: #edf6ff, lightness 97 of 100. Against white 1.09 to 1, which fails AA at every text size; against black 19.22 to 1, which passes AA for normal text.
  2. Step 100: #bbdfff, lightness 89 of 100. Against white 1.38 to 1, which fails AA at every text size; against black 15.11 to 1, which passes AA for normal text.
  3. Step 200: #86c6ff, lightness 81 of 100. Against white 1.82 to 1, which fails AA at every text size; against black 11.53 to 1, which passes AA for normal text.
  4. Step 300: #6cace4, lightness 72 of 100. Against white 2.42 to 1, which fails AA at every text size; against black 8.65 to 1, which passes AA for normal text.
  5. Step 400: #5393c9, lightness 64 of 100. Against white 3.28 to 1, which passes AA for large text only — 24px, or 18.66px bold; against black 6.38 to 1, which passes AA for normal text.
  6. Step 500: #3f7fb4, lightness 58 of 100. Against white 4.28 to 1, which passes AA for large text only — 24px, or 18.66px bold; against black 4.90 to 1, which passes AA for normal text. It is your own colour, at its exact hex.
  7. Step 600: #1f6194, lightness 48 of 100. Against white 6.57 to 1, which passes AA for normal text; against black 3.19 to 1, which passes AA for large text only — 24px, or 18.66px bold.
  8. Step 700: #004a79, lightness 40 of 100. Against white 9.31 to 1, which passes AA for normal text; against black 2.25 to 1, which fails AA at every text size.
  9. Step 800: #003457, lightness 31 of 100. Against white 12.89 to 1, which passes AA for normal text; against black 1.62 to 1, which fails AA at every text size.
  10. Step 900: #001f37, lightness 23 of 100. Against white 16.78 to 1, which passes AA for normal text; against black 1.25 to 1, which fails AA at every text size.
  11. Step 950: #000c1a, lightness 15 of 100. Against white 19.67 to 1, which passes AA for normal text; against black 1.06 to 1, which fails AA at every text size.

Both figures are floored to two decimals, never rounded up, so each one is a ratio that step genuinely reaches. The word under a figure is its WCAG 2.2 AA verdict: AA means it clears 4.5:1 for normal text, large means it clears only the 3:1 allowed at 24px, or 18.66px bold.

  • Step 500 is your own colour, at its exact hex. Every other rung is derived from it — same hue, same chroma where sRGB can hold it, an even ladder of lightness.
  • 600 is the lightest step that clears 4.5:1 against white, at 6.57.
  • 500 is the darkest that clears it against black, at 4.90.
  • No step clears it against both grounds. That is the usual answer, not a fault in the ramp: the two figures on a row always multiply to 21, so the window for passing on white and on black is 4.50 to 4.66 against white and nothing here lands in it.

What a tint and a shade actually are

The words are older than the screen. A tint is a colour mixed with white, a shade is the same colour mixed with black, and a tone — the one nobody asks for and everybody uses — is a colour mixed with grey, which lowers its saturation without moving it toward either end. In every case the hue is meant to survive the mix: a lighter blue is still that blue, or the ramp has stopped being a ramp of one colour and become a collection of several.

What a design system means by “tints and shades” is narrower and more useful: one hue at a fixed set of lightnesses, numbered so that any part of the interface can ask for “the 700” and get a predictable answer. The 50 to 950 ladder above is the convention Tailwind popularised and most systems now copy. It is a naming scheme, not a standard — nothing in it is defined by a specification, and the rung numbers mean only what the ramp that produced them decided they mean.

The ramp above is built by stepping lightness and holding hue and chroma, which is not quite the same as mixing in white or black and is better behaved. Mixing toward white pulls a colour toward every white pixel’s hue-lessness at the same time as lightening it; stepping lightness keeps the hue exactly and lets chroma fall only where it has to. You can watch that happen on the colour the tool opens with: #3f7fb4 carries a chroma of 0.105, held across the middle of the ramp and tapering to 0.015 at the 50 step and 0.039 at the 950. That is not a stylistic decision. sRGB simply cannot hold that much chroma at lightness 97 or lightness 15, so each step is brought back into the gamut at the same lightness and hue rather than being clipped into a colour nobody chose.

Why equal lightness steps are not equal perceived steps

Every ramp generator claims even steps. The question is even in what, and the usual answer is HSL, because HSL is what CSS shipped with and hsl(210 60% 50%) reads like a colour at half lightness. It is not one. HSL’s L is a coordinate in a cylinder wrapped around RGB, and it takes no account of the eye being far more sensitive to green than to blue. Pure yellow and pure blue are both 50% lightness in HSL. Measured in OKLCH, whose lightness axis is built from perceptual experiments, #ffff00 sits at L 97 and #0000ff at L 45 — the same number in HSL, and half the visible range apart to a person.

That is why the ramp above is stepped in OKLCH. Within one hue the two spaces disagree less dramatically, but a design system does not have one hue: it has a blue, a green, an amber and a red, and it needs the 600 of each to read as the same weight beside the others. Even steps in HSL give you four ramps whose middles sit at four different apparent lightnesses, which is the reason a palette built that way looks fine swatch by swatch and unbalanced as a set. Even steps in OKLCH’s L give you rungs that land in the same place to the eye, whatever the hue.

It is worth being honest about the limit. OKLCH is a good model of perceived lightness and not a perfect one — it under-accounts for the Helmholtz–Kohlrausch effect, where a highly saturated colour looks lighter than a grey of the same lightness — so a very chromatic ramp can still read slightly unevenly at its most saturated rungs. It is the best widely available answer, it is dramatically better than HSL, and it is not magic.

Why the achieved ratio is the number that matters

A ramp’s labels are positions. The 500 is the middle rung because it is the middle rung, and every generator that stops there is asking you to take the useful part on trust. The useful part is what each step will do when text goes near it, and that is a measurement rather than a convention: this page reports the WCAG 2.2 contrast ratio each step actually achieves against white and against black, so the answer arrives in the same row as the swatch instead of one paste-into-another-tool away.

Two hues at identical OKLCH lightness do not reach identical ratios, which is the clearest argument for measuring rather than assuming. Take twelve colours around the wheel at L 62, chroma 0.14: against white they run from 3.42:1 at green through 3.90:1 at magenta — a 14 per cent spread at what OKLCH calls the same lightness, because WCAG luminance weights the channels differently from perceptual lightness and always will. None of the twelve clears 4.5:1. A ramp that told you those were all “the 400” would be telling you the truth and nothing you could use.

The figures are floored to two decimals rather than rounded, for the reason the contrast checker sets out at length: a step measuring 4.4988 printed as “4.50” is a figure it never reached, sitting above the word fails. Rounding down can only ever understate, which is the safe direction when the number is going into an accessibility claim.

The two figures on a row always multiply to 21

This is the part worth taking away, and it is arithmetic rather than opinion. WCAG contrast against white is 1.05 ÷ (Y + 0.05) and against black is (Y + 0.05) ÷ 0.05, where Y is the colour’s relative luminance. Multiply them and Y cancels: every colour on earth splits a fixed budget of 21 between the two grounds. Check any row above — the printed figures land a hair under 21 only because both have been floored.

Two useful things fall out of that. A step that clears 4.5:1 against white has at most 21 ÷ 4.5 = 4.66 left against black, so the window for a colour that carries body copy on a light ground and a dark one is 4.50 to 4.66 against white — narrow enough that most ramps contain no such rung at all, and the notes under the ramp above say whether this one does. #767676, the grey the contrast checker uses as its passing example, is inside it at 4.54 and 4.62. And there is no such thing as a colour that fails against both: falling short of 4.5 on white guarantees better than 4.66 on black. If a step is unusable in light mode it is comfortably usable in dark mode, which is the single most useful fact a ramp can tell you and the one a grid of hexes cannot.

What a ramp cannot decide for you

A ratio is a floor, not a verdict on legibility. It knows nothing about the typeface, the weight, the size above the minimum, or whether the text sits over a photograph where the background changes underneath it. Nor does the ramp know what your steps are FOR: a 950 that measures 19.67:1 against white is a fine ink and a punishing body colour for long-form reading, and a 200 that fails everything is exactly right as a surface tint behind dark text. Use the figures to rule out what cannot work, then look at the result at the size you actually ship.

When eleven steps aren’t the eleven you wanted

This page builds one ramp: eleven steps, evenly spaced in lightness, and it tells you what each one achieved. Scale mode is the same engine with the decisions handed back — 5 to 15 steps, either labelling convention, a contrast shift that widens or narrows the whole span, and a second algorithm that works the other way round: instead of stepping lightness and reporting the ratio, it takes a target ratio for every step and searches for the lightness that hits it, then shows you how far off it landed and why.

Open the ramp with its controlsIt opens on the 11 steps above, built from the colour in the field — the link carries your ramp, not a default.

Opens Scale mode. Free, no sign-up, and it runs in your browser like this page does.