The 4-point grid, and why 16 makes it easy
Every browser ships with a default font size of 16px. That is what medium means, what
1rem resolves to until someone changes it, and — less obviously — the reason spacing
systems on the web settle on 8 or 4. Sixteen is 2⁴. It divides evenly by 2, 4 and 8, so a
unit chosen from those three lines up with the text it sits beside without anyone
doing arithmetic.
The 8-point grid
The idea most people learned first is Elliot Dahl's: size and space everything in increments of 8. Heights, widths, margins, padding — multiples of 8, no exceptions. The case for it was consistency across a team (a developer can eyeball an 8 without measuring) and clean scaling across pixel densities: an odd number like 5 becomes 7.5 at 1.5× and renders as a smear, while 8 becomes 12 and stays crisp. Most screen widths are divisible by 8, so the layout fits the device and the components fit the layout.
That argument still holds. The place it pinches is inside a component. A badge with 8px of padding is generous; with 0 it is naked; and the number you actually want is 4. Icon gaps, input padding, the space between a label and its field — the small stuff wants a half step.
Why 4
A 4-point grid is the 8-point grid with the half step admitted. Everything that was on the 8 grid still is (8 is a multiple of 4), and the tight cases get 4, 12, 20 instead of being rounded to the nearest 8 or hand-tuned to 5 or 6.
Does 4 scale? Check it against the density multipliers that actually ship: 4 × 1.25 = 5, 4 × 1.5 = 6, 4 × 1.75 = 7, 4 × 2 = 8, 4 × 3 = 12. Whole numbers at every step. The half-pixel argument was against 5 and 6 and 10, never against 4.
What 4 costs is choice: a scale that runs 4, 8, 12, 16, 20, 24, 32, 40, 48, 64 has more values than one that runs 8, 16, 24, 32, 48, 64, and more values is more decisions. The answer is to treat 4 as the unit and still reach for the 8s most of the time. The 4s and 12s are for when the 8 is visibly wrong.
Tailwind already decided this
Tailwind's spacing scale is a 4-point grid. p-1 is 4px, p-2 is 8, p-3 is 12, p-4
is 16, p-6 is 24, p-8 is 32 — the number is the count of units, and the unit is
0.25rem, which is 4px at the browser default. In Tailwind 4 it is one variable:
@theme {
--spacing: 0.25rem; /* the default: 4px at a 16px base */
}
Change it and every spacing utility follows. Set --spacing: 0.5rem and you have an 8-point
grid with the same class names — p-2 is now 16px. Set 0.125rem and you have a 2-point
grid for something dense like a data table. The classes do not know or care; they count
units.
Two things fall out of the unit being in rem rather than px:
- A reader who sets their browser to 20px text gets a 5px unit, and the whole layout
breathes proportionally. Spacing in
pxwould leave bigger text in the same tight boxes. - The grid is still "16 divides by 4" at the default, which is the case that matters for pixel-snapping; at other sizes the browser is already sub-pixel positioning the text.
What is on the grid and what is not
Spacing and box sizes go on the grid. Type sizes do not have to — 14, 18 and 30 are all fine text sizes and none is a multiple of 4 — but line heights should, because a line height is a box the next block sits against. Sixteen-pixel text with a 24px line is three units of 8 or six of 4; 18px text at 28 is seven units of 4. That is what makes stacked blocks of different sizes still land on shared lines, and it is the whole of what "vertical rhythm" means in practice. Choosing the sizes is its own decision.
Borders are the usual exception: a 1px hairline is not on any grid and does not need to be. Dahl's follow-up on borders and layouts is about exactly that — whether the border is inside the 8 or added to it — and the honest answer is to pick one and write it down.
Here
This site runs Tailwind's default unit. There is no --spacing override in main.css,
which is a decision too: the 4 is the grid, the 8s are the habit, and a component that
needs a 5 is a component that needs looking at.
Sources
- Elliot Dahl, Intro to the 8-Point Grid System, 2016 — the article that made the case; the scaling argument above is his.
- Tailwind CSS, Theme variables — spacing — the
--spacingvariable and what derives from it.