The base should divide common screen densities
Aliases: spacing base · 4pt grid · pixel snapping
What it is
A spacing base, multiplied by 2x or 3x, should land on whole device pixels. Four and eight are common because 4×2=8 and 4×3=12 — no half pixel. Pick 5, and 1.5x Android yields 7.5. If left and right round opposite ways, boxes go soft and a 1 px rule is fat on one side.
The only question is whether the arithmetic divides. Not how many steps the scale has, and not whether exceptions will wreck it.
Why it happens
Layout math runs in logical pixels; the screen expands them by density. Odd numbers, or a tasteful 5 or 6, times 1.5 or 2.75, produce fractions. Rasterization then snaps: neighbouring edges may floor and ceil differently, so two edges that should meet miss by half a pixel and strokes look drunk.
Touch and type already fight for whole pixels. Spacing that adds another crop of halves dirties the page in a way nobody can name, especially stacked cards and hairlines. A base that divides the densities you ship closes the error before rasterization.
Where it stops holding
Surfaces that draw vectors to an offscreen texture and scale (some games, some maps) mostly skip this box model; the base constraint is weak. A single 3x handset can hide multiples of 5; add 1.5x, 2.75x or 1x desktop and it shows. When users set display zoom to 125% or 150%, even multiples of 8 can stop dividing. Then “divide when you can” plus a blur check at the target zoom is sturdier than assuming one base is immortal.
Applying it
- After picking a base (often 4), list target densities (1, 1.5, 2, 2.75, 3) and OS display zoom. For each, check whether
base × densityis an integer or an acceptable round. - Treat 1 px rules as their own problem: physical pixels or a hairline path, not a hope that 5 px padding will “carry” a crisp line.
- How to check: open the same list on 1.5x and 3x simulators and zoom the card edge and the divider. One side soft, one side crisp, or left/right padding looking unequal: note the logical value. Snap it to a base multiple and see whether the blur dies.