Why this exists
Most color palettes are built at the edge of what a screen can show. Measured across the eighteen chromatic palettes that ship with Tailwind v4, every stop sits between 0.96 and 1.10 of the highest chroma sRGB allows at that stop’s lightness and hue. The bell curve the raw chroma numbers appear to trace is not a designed curve at all — it is the shape of the sRGB gamut.
That is the right choice for an accent. It is the wrong one for most of an interface. Surfaces, cards, borders, dividers, muted text, disabled states: none of them want to be as saturated as the display can manage. Palettes made of nothing but candy colors leave you to invent the quiet nine tenths yourself.
The usual answer is a second, unrelated palette — slate, zinc, stone. Different hue, different lightness steps, no relationship to the brand color. They cannot stand in for one another, because they do not line up.
Componiq Colors pairs them instead. Every step carries a vivid tone and a muted tone at the same lightness. The two behave identically against text and differ only in intensity, so either can take the other’s place in a token set.
The gap that closes is measurable:
| vivid + saturation ramp | 0 tones | dark and quiet |
| muted ramp alone | 4 tones | #434460 #303145 #1d1e2a #0a0b0f |
Chroma is not free
A very light or a very dark color cannot be very saturated. There is no dark, vivid yellow — dark and yellow exclude each other physically, not by convention. So the maximum chroma available depends on both lightness and hue. For orange at hue 60:
| lightness 95% | 0.031 | |
| lightness 87% | 0.086 | |
| lightness 79% | 0.149 | |
| lightness 70% | 0.164 | widest |
| lightness 50% | 0.117 | |
| lightness 35% | 0.082 | |
| lightness 15% | 0.035 |
The chroma slider shows this directly. The hatched part of the track is not disabled, it is empty: dragging into it produces no more color, because none exists there. Showing the boundary beforehand beats letting you discover it by wondering why nothing changes.
What OKLCH is doing
Every stop is generated in OKLCH and then mapped into sRGB by reducing chroma while holding lightness and hue.
The alternative — clipping the red, green and blue channels back into range — moves both. A color asked to be more saturated than the display allows comes back as a different color, not merely a duller one. Reducing chroma keeps the ramp’s shape: every stop still sits at the lightness the algorithm chose, in the hue you picked.
The seven algorithms
The algorithm setting decides how a ramp grows out of your seed color. There are two families. The first three build every stop in OKLCH and then bring it back into sRGB by lowering chroma, as described above. The last four work in plain HSL, where every value is already on screen, so nothing needs mapping.
- Tailwind CSS
- Copies the shape of Tailwind v4's own palettes: how light each stop is, and how much color it carries, measured across all eighteen of them. The ramp also bends toward your hue. A yellow is lightest where yellow can be most vivid, a blue sits lower down. Pick this for a ramp that feels like the ones people already know.
- Linear
- Even lightness steps from near white to near black, with every stop as saturated as your seed allows. The simplest shape there is. Pick it when the ramp should read as a plain gradient, or as a starting point you will tune with the sliders.
- Contrast (WCAG)
- Turns the question around. Instead of choosing how light each stop is, it chooses how much contrast each stop has against white, from almost none up to about 17 to 1, and lets lightness follow. Because every stop is solved to a ratio, none of them can carry your seed exactly. Pick it when you have to promise contrast numbers.
- Lightness Scale
- Keeps your seed's hue and saturation and only walks lightness, from 95% down to 5%. A straight tint-to-shade ramp, the way most people would make one by hand.
- Saturation Scale
- Keeps the hue, and raises saturation from 10% to 100% while lightness falls from 90% to 20%. The light stops come out almost gray, the dark ones fully colored. Pastel at the top, deep at the bottom.
- Hue Shift Scale
- Keeps the saturation, walks lightness from 90% to 20%, and turns the hue a little as it goes: 15 degrees to one side at the light end, 15 to the other at the dark end. This is the warm-to-cool lean hand-made palettes have and a plain darken() ramp does not.
- Muted Scale
- The same lightness steps as the Lightness Scale, with saturation held at a quiet 18%. Tinted neutrals: still recognizably your hue, never a second accent. Made to sit next to the Lightness Scale, so each step has a vivid and a muted tone at the same lightness.
The seed-is-a-stop switch only works with the first two. Tailwind and Linear can move a stop onto your exact color; Contrast cannot, because its stops are already spoken for, and the HSL scales never look for one.
Contrast shift
The shift bends where along the ramp each stop samples from, rather than moving stops one at a time. Positive values push the whole ramp darker, negative ones lighter, and both ends stay pinned. One control, and the spacing stays even.
| −1.00 | #c4ccfa | 1.57:1 on white |
| −0.50 | #8f9afa | 2.57:1 |
| 0.00 | #6a6dfb | 4.04:1 |
| +0.50 | #4d04fe | 7.60:1 |
| +1.00 | #4514e4 | 8.51:1 |
Alpha ramps
A translucent token is only useful if it lands on the same color as its solid twin. Then the two are interchangeable: one knows what it sits on, the other does not, and a component can take either. That requirement leaves exactly one free choice per stop, and spending it on the smallest workable opacity shows as much of the real backdrop as possible.
The obvious construction — one saturated tone per hue at fourteen opacities — covers the light two thirds and then stops. A color over white can never composite to something darker than itself, so at full opacity the ramp is stuck while the ladder keeps descending:
| stop 1 | #fff6f7 vs #fef6f6 | 0.002 |
| stop 6 | #fda0a8 vs #fba29f | 0.015 |
| stop 13 | #fa3d4e vs #4d0e13 | 0.393 |
| stop 14 | #fa3d4e vs #270406 | 0.498 |
Gray is the case where the solve collapses into something familiar. Over white the answer is always pure black and over black always pure white, so the two overlay ramps are the neutral ladder read as nothing but opacity — not a separate design.
| over white | α = 1 − L | #00000024 → #dbdbdb |
| over black | α = L | #ffffff18 → #181818 |
Opacity and every channel are stored as bytes, and compositing on that grid is lossy — solving on paper and rounding misses by one bit on about a quarter of the stops. Each one therefore searches upward from its theoretical floor until the whole triple composites back exactly, which usually takes no steps at all and never more than a handful.