Learn CSS · Lesson 4 of 7 · 8 min
The box model
Here is the single idea that makes CSS layout click: every element on the page is a rectangular box, and that box is built from four layers stacked around each other. Once you can see those four layers, spacing stops being trial and error.
The four layers
From the inside out, every box has content, then padding, then a border, then margin. Each one wraps the one before it. This is exactly what your browser's DevTools draws when you inspect an element:
- Content is the actual stuff: your text, image or child elements. Its size is set by
widthandheight(or by the content itself). - Padding is space inside the box, between the content and the border. It shares the box's background, so padding is where a card gets its comfortable inner breathing room.
- Border is the line drawn around the padding. It has a width, style and color.
- Margin is space outside the box. It is always transparent and is how a box pushes other boxes away from itself.
The quick rule of thumb: padding is space on the inside, margin is space on the outside. Reach for padding when you want room around content within the same element; reach for margin when you want to separate one element from its neighbours.
.card {
width: 300px;
padding: 24px; /* inner breathing room */
border: 1px solid #e6e7eb; /* the visible edge */
margin: 16px; /* gap to other elements */
} The width trap: box-sizing
This is the box model's most famous gotcha, and the one that confuses every beginner. By default
(box-sizing: content-box), width sets the size of the content only.
Padding and border are then added on top. So this card is not 300px wide on screen:
.card {
box-sizing: content-box; /* the default */
width: 300px;
padding: 24px; /* + 24 left + 24 right */
border: 1px solid; /* + 1 left + 1 right */
}
/* actual rendered width = 300 + 48 + 2 = 350px */ That surprise overflow, where adding padding makes a box wider than you asked for, is the box model
biting you. The fix is one line, and nearly every codebase on the web ships it: switch to
border-box, which makes width mean the total width, with padding and
border fitting inside it.
*, *::before, *::after {
box-sizing: border-box;
}
/* now width: 300px means the box is 300px, full stop */ Put that snippet at the top of every stylesheet you write. With border-box, the number you
type is the number you get, and layout math becomes addition you can do in your head.
Margins collapse (the second surprise)
Vertical margins between stacked block elements do not add up; they collapse into the
larger of the two. If one paragraph has margin-bottom: 30px and the next has
margin-top: 20px, the gap between them is 30px, not 50px.
This is deliberate (it keeps text spacing even), but it trips people up. If you want predictable,
non-collapsing gaps, set spacing in one direction only (a common convention is margin-top on everything),
or use gap on a flex or grid container, which never collapses. More on those in the
flexbox and grid lessons.
Seeing the boxes yourself
The fastest way to internalize this: make the boxes visible. Drop a temporary outline on everything and
the page's structure appears instantly. (Use outline, not border, because outline
does not take up space and so will not shift your layout while you debug.)
* { outline: 1px solid rgba(255, 0, 0, .35); } Better still, open your browser DevTools, inspect any element, and look at the box-model panel. It shows the exact content, padding, border and margin values in pixels, color-coded just like the diagram above.
Practice
Two minutes each, and each one locks in a single idea. Use a blank CodePen, your browser's DevTools, or one of our tools to experiment:
- Build a 320px card with
padding: 32pxand a4pxborder. Measure its real width undercontent-box, then addbox-sizing: border-boxand confirm it becomes exactly 320px. - Stack two paragraphs. Give the first
margin-bottom: 40pxand the secondmargin-top: 20px. Confirm the visible gap is 40px, not 60px. You just watched margins collapse. - Style a button with only padding (no fixed width or height) and watch it size itself to its label plus that padding. That is the box model building the box around your content for you.
The mental model to keep
- Every element is a box with four layers: content, padding, border, margin.
- Padding is inside (and tinted by the background); margin is outside (and always transparent).
- Set
box-sizing: border-boxglobally sowidthmeans the whole box. - Vertical margins collapse to the larger value; use
gapwhen you want that to never happen.
That is the box model. It is the foundation under every other layout topic, so it is worth getting comfortable here before moving on to where boxes actually go on the page.