Skip to content
Sahil Durgia/ full-stack
2 min readCSS & Tailwind

The CSS Box Model Explained (With Diagrams)

Every element is four nested boxes. content-box vs border-box changes what 'width: 200px' actually means — the top source of unexpected layout math.

CSSbox modelfundamentals

Every single element on a page is, geometrically, four nested boxes: content, padding, border, and margin, from the inside out. Almost every "my layout math doesn't add up" bug traces back to a wrong assumption about which of these `width` and `height` actually refer to.

The four boxes, from the inside out

  • Content box — the actual text or child elements.
  • Padding — transparent space inside the border, part of the element's clickable/background area.
  • Border — a visible (or invisible) line around the padding.
  • Margin — transparent space outside the border, separating this element from its neighbors — and margin is the one that never has a background color, because it isn't part of the element at all.

content-box vs border-box: the actual gotcha

/* content-box (the old CSS default) */
.box-a { box-sizing: content-box; width: 200px; padding: 20px; border: 2px solid; }
/* Rendered width = 200 + 20*2 + 2*2 = 244px — width excludes padding/border */

/* border-box */
.box-b { box-sizing: border-box; width: 200px; padding: 20px; border: 2px solid; }
/* Rendered width = 200px, full stop — padding and border eat into the content area instead */

With `content-box` (the historical CSS default), `width: 200px` sets only the content area — padding and border add ON TOP of that, so the element's actual rendered width is larger than the number you wrote. With `border-box`, `width: 200px` is the final, total rendered width — padding and border are subtracted from the content area to fit inside it. This is exactly why nearly every modern CSS reset (including Tailwind's Preflight) sets `box-sizing: border-box` globally: it makes `width` mean what almost every developer intuitively expects it to mean.

Why margin collapsing is its own separate gotcha

Two vertically adjacent block elements' margins don't add — the larger one wins, and the smaller one is absorbed. A 20px margin-bottom next to a 30px margin-top produces a 30px gap, not 50px. This trips up anyone assuming margin behaves like padding (which never collapses) — it's a genuinely different, CSS-specific rule worth knowing by name so the behavior reads as expected instead of a bug.

Keep reading
Next: CSS specificity

Part 2 of the CSS and Tailwind series.