What Is a JND — When Two Colors Look the Same
Here is a five-second experiment. Two grays: #808080 and #828282. Put
them side by side, edges touching, and decide which is lighter. In OKLCH
lightness they sit at ≈0.600 and ≈0.607 — a difference most viewers cannot
find even at the shared edge. Now replace the second swatch with #868686,
at ≈0.620: for most people a faint seam appears where the swatches meet.
Slide them apart, and for many viewers even that difference dissolves.
The line the experiment crosses has a name: the just-noticeable difference (JND) — the smallest change in a stimulus that an observer can reliably detect. Anything smaller is not a subtler difference; perceptually it is no difference. For color scales the consequence is blunt: two steps closer than a JND are one color with two names. In OKLCH lightness, a difference of about 0.02 L is a workable threshold for UI work.
Where that threshold comes from, how palettes end up violating it, and what it costs when they do — that is this article. The color model the threshold is measured in has its own series in our OKLCH guide.
Where does the idea of a JND come from?
From psychophysics, the research tradition that measures how physical change maps to experienced change. The just-noticeable difference has been studied since the nineteenth century, beginning with Ernst Weber’s experiments on lifted weights: how much heavier must a weight become before a person notices? The recurring finding is that detection tends to scale with proportion — a small addition is obvious against a light load and invisible against a heavy one — and the same pattern holds across brightness, loudness, and, with more dimensions involved, color.
Two properties of the concept matter for design work. First, a JND is a statistical quantity: “reliably detect” means detected in some agreed share of trials, not a switch that flips. Second, it moves with conditions — adjacent patches reveal smaller differences than separated ones, large areas more than thin lines, calm surrounds more than busy ones. Any single number is therefore an engineering rule of thumb calibrated to typical viewing, not a constant of nature. In color science the general-purpose measure of difference is delta E, and a JND corresponds to roughly ΔE 1–2 — an order of magnitude, not a precise constant. The 0.02 figure for OKLCH lightness is the same idea projected onto the one axis palettes are mostly built along.
How close is too close between palette steps?
Run the numbers on a full-range UI ramp. A scale from near-white to near-black might span lightness 0.97 down to 0.25 — a budget of 0.72 to distribute. Steps sit at the ends of gaps, so n steps make n − 1 gaps:
| Steps | Gaps | L per gap | Reading |
|---|---|---|---|
| 10 | 9 | 0.080 | comfortable — four times the threshold |
| 25 | 24 | 0.030 | approaching the line |
| 40 | 39 | ≈0.018 | below it — adjacent steps merge |
And that assumes perfectly even spacing. Many real ramps ease their curves near the ends, so the tightest pair is tighter than the average — trouble arrives before the average gap reaches 0.02.
Scale Composer checks this pair by pair: a JND warning fires whenever two adjacent steps land within 0.02 L of each other. Open a ramp built to trip it — dozens of steps on a shallow lightness curve. The flagged pairs are precisely the neighbors you will not be able to tell apart.

Where do near-JND steps come from?
Two producers account for most cases:
- Too many steps for the lightness span. The 40-step ramp above is the obvious version. The subtle version is a narrow span: a dark-mode surface stack confined between L 0.45 and 0.25 has only 0.20 to spend, so twelve steps make eleven gaps of ≈0.018 each — below threshold, even though twelve steps across the full range would be generous.
- Ramps flattened against the gamut ceiling. A screen can only display so much chroma at each lightness; steps pushed past that limit are clipped back to the nearest displayable color, and clipping erases distance — two steps distinct in the model can land nearly on top of each other on screen. This is one reason generators cap chroma slightly below the ceiling: the headroom preserves the differences the lightness curve promised.
Why do merged steps matter beyond aesthetics?
A palette is, functionally, a signaling alphabet: each step is worth exactly the visible difference between it and its neighbors. A step below the JND adds a name to the vocabulary but no signal — cost without information. Two failures follow directly:
- False choices. A token set offering
gray-200andgray-250that no one can distinguish forces decisions with no visible consequence. The team debates which one is correct, the interface looks identical either way, and the inconsistency stays invisible until an audit counts tokens instead of looking at screens. - Broken state signaling. If a card’s rest and hover backgrounds sit 0.015 L apart, the product has an interaction state users cannot perceive. The feedback works in the design review, where someone toggles the two states back and forth, and fails in use, where nobody does. Disabled versus enabled, selected versus unselected — any state pair mapped onto a sub-threshold step inherits the same silence.
What do you do when the warning fires?
Both honest repairs are subtractive: fewer steps across the same span, or a wider span under the same steps. What does not help is nudging the flagged pair apart by hand — that just relocates the crowding to the next pair — and what should not be touched is the threshold itself, because the limit lives in observers, not in software. Open the repaired version of the same ramp — the same lightness span carrying a step count it can support: every adjacent gap sits back above 0.02, and any two neighbors are once again two colors you can tell apart.