Box model — what "width" actually refers to
Layouts that don't line up to the pixel, cards you laid out four across that wrap onto the next row — a lot of these break because the value you gave width is not the width you thought it was.
CSS treats every element as a rectangular box. The structure of that box is decided by the box model.
What you'll learn in this chapter
- The four regions that make up the box model, and what each is for
- That
widthrefers to the content region only by default, and howbox-sizingchanges that - How far the background gets painted, and where it stops
- When top-and-bottom margins collapse, and how to stop them
If you have written width or padding in CSS before, you're ready.
The four regions
The box of an element is a nested structure of four regions, from the inside out.
The order from inside out is content → padding → border → margin. It's worth memorizing. The fact that padding sits inside the border and the margin sits outside it explains both the background painting range and margin collapsing later in this chapter.
| Region | Role | Does the background paint here? | Relationship with other elements |
|---|---|---|---|
| Content | Where the text or image itself lives | Yes | — |
| Padding | Space between content and border | Yes | Inside the box, so it doesn't affect other elements |
| Border | The boundary of the box | Yes by default | Sets the outer edge |
| Margin | Space between one box and another | No | Pushes neighboring elements away |
Padding and margin are both "space", but they behave differently. Padding grows the inside of the box, so the background color or image extends that far. Margin is space outside the box, so no background reaches it.
The four sides can be set individually
padding, margin, and border all have shorthand forms that set all four sides at once, and longhand forms that set each side separately.
/* Longhand — set each side */
.card {
padding-top: 8px;
padding-right: 16px;
padding-bottom: 8px;
padding-left: 16px;
}
/* Shorthand — the number of values changes the interpretation */
.card {
padding: 8px; /* All four sides: 8px */
padding: 8px 16px; /* Top and bottom: 8px / left and right: 16px */
padding: 8px 16px 24px; /* Top: 8px / left and right: 16px / bottom: 24px */
padding: 8px 16px 24px 32px; /* Top → right → bottom → left (clockwise) */
}
The four-value shorthand is clockwise: top, right, bottom, left. In the three-value form, the left side is omitted and takes the value of the right. In the two-value form, the two values pair up as top-and-bottom and left-and-right.
What width refers to
This is the single most commonly misunderstood point in the box model.
By default, width refers only to the content region. Padding and border are added on the outside.
.card {
width: 350px;
padding: 25px;
border: 5px solid;
}
The horizontal space this element occupies on screen is not 350px.
350px (content) + 25px×2 (padding) + 5px×2 (border) = 410px
You thought you had set the content to 350px, but you actually built a box that overshoots by 60px. If you set up a three-column grid at width: 33.3% and it wraps because of the padding, this is why.
This default behavior is called the standard box model (box-sizing: content-box).
box-sizing: border-box changes the interpretation
Setting the box-sizing property to border-box changes what width means.
.card {
box-sizing: border-box;
width: 350px;
padding: 25px;
border: 5px solid;
}
Now the whole box fits within 350px. Padding and border eat into it, and the content region gets whatever is left.
350px (whole box) − 25px×2 (padding) − 5px×2 (border) = 290px (content)
content-box (default) | border-box | |
|---|---|---|
What width refers to | Content region only | Content + padding + border |
| Adding padding | Grows the whole box | Shrinks the content region |
| Total box width | Larger than the value you set | Matches the value you set |
For laying things out, border-box matches intuition better. If you say "this box is 350px", you want it to take up 350px. That's why applying it across the whole project as a reset has become the idiom.
*,
*::before,
*::after {
box-sizing: border-box;
}
The reason pseudo-elements are included is to keep ::before and ::after on the same calculation rules when they carry padding or borders. Utility frameworks like the ones covered in the Tailwind CSS Guide ship this reset by default. So using Tailwind makes border-box feel like the natural behavior — but in plain CSS, content-box is the default. Keep that in mind.
box-sizing does not include marginsEven with border-box, the margin stays outside width. What "the whole box" contains only goes up to the border; the margin is space between boxes. When widths don't add up in a horizontal layout, suspect the margin first.
How far the background gets painted
The background-clip property decides how far the background color or image is painted. The initial value is border-box.
So by default, the background extends beyond the content region into the padding region and the border region as well. It does not extend into the margin region.
.card {
background-color: #eef;
padding: 24px; /* Background color reaches into this 24px too */
border: 8px dashed; /* You can see the background through the gaps in the dashes */
margin: 24px; /* Nothing here */
}
You won't notice with a solid border, but with dashed or dotted — or with a semi-transparent border — you can see the background through the gaps. That's the evidence that the background is painted underneath the border.
Changing the value of background-clip narrows the range.
| Value | How far the background is painted |
|---|---|
border-box (initial) | To the outer edge of the border |
padding-box | To the outer edge of the padding. Not under the border |
content-box | Content region only |
text | Clipped to the shape of the text |
"Padding to create space, and the background color follows along" is used routinely in card and button design. When you use padding to grow both the hit area and the visual area of a button, the background comes with it, so nothing looks off.
Margin collapsing
Suppose two elements stacked vertically have margin-bottom: 20px and margin-top: 30px. You'd expect 50px of space between them, but the actual gap is 30px.
This is margin collapsing. It happens only for vertical margins, never for left-and-right ones.
The three situations where it happens
1. Between adjacent siblings
<p style="margin-bottom: 20px">Previous paragraph</p>
<p style="margin-top: 30px">Next paragraph</p>
The gap is not 20px + 30px = 50px; it is the larger of the two, 30px.
2. Between a parent and its first or last child
When the parent has no border-top and no top padding, and there is no inline content before the first child, the parent's margin-top collapses with the margin-top of its first child. The same applies at the bottom: if there is no inline content after the last child, and the parent has no height / min-height / border-bottom / padding-bottom, the parent's margin-bottom collapses with the last child's margin-bottom.
The phenomenon of "the margin you put on the child ends up outside the parent" is this.
3. An empty block
A block with no border, no padding, no inline content, no height, and no min-height collapses its own top and bottom margins together.
The sign of the values changes the result
| Combination | Collapsed value |
|---|---|
| Both positive | The larger of the two |
| Both negative | The smaller of the two (the most negative) |
| Positive and negative mixed | The sum of the largest positive and the most negative |
For example, margin-bottom: 30px and margin-top: -10px collapse to 30 + (−10) = 20px.
How to stop collapsing
To prevent unintended collapsing, put something between the two margins that would collapse. The four below all address situation 2 (parent and child).
- Add even 1px of
padding-top/padding-bottomto the parent - Add
border-top/border-bottomto the parent - Make the parent
display: flexordisplay: grid - Establish a new block formatting context on the parent (with
overflow: auto, for example)
Of these, only flex / grid stops situation 1 (adjacent siblings). Padding, borders, and overflow: auto on the parent only separate the parent from its child, so they do nothing for collapsing between siblings. Situation 3 (an empty block) is stopped by any one of that block's own border, padding, inline content, height, or min-height.
Margins do not collapse inside a Flexbox or Grid container because those two layout models have their own layout rules. One reason recent layouts run into collapsing less often is that these two have become mainstream, and gap is now used for spacing. The actual patterns are covered in Flexbox layout and Grid layout.
Margins on floated elements and absolutely positioned elements don't collapse in the first place.
Common misconceptions
"padding and border are always included in width." — Whether they are is decided by box-sizing. With the default content-box, they are not included; they are added on the outside. Only when you specify border-box do they become included. Many projects apply border-box in a reset, so it can feel like "of course it's included" — but that's a project setting, not the CSS default.
"padding moves in lockstep on all four sides and can't be set individually." — It can. Use the longhand like padding-top, or use the shorthand with two, three, or four values.
"Background color is only applied to the content region." — By default it is background-clip: border-box, so the background extends into the padding and border regions too. The only region it doesn't reach is the margin.
"Margins are always additive." — Vertical margins collapse. Horizontal margins don't, so they add up. Different behavior in different directions is a source of confusion.
"Setting box-sizing: border-box also includes margins." — It doesn't. What border-box includes stops at the border.
Exercises
Q1. How many pixels wide does the following element take up on screen?
.box {
width: 200px;
padding: 10px 20px;
border: 2px solid;
margin: 16px;
}
Answer and explanation
Answer: 244px
There's no box-sizing, so the default content-box applies. width refers to the content region alone.
200px (content) + 20px×2 (left+right padding) + 2px×2 (border) = 244px
Margin is space outside the box, so it doesn't count toward the box's own width. It does affect the space to the next element, so if you're thinking about how much the element occupies in the layout, budget 32px for that separately.
Vertically, 10px×2 + 2px×2 = 24px is added on top of the content height.
Q2. If you add box-sizing: border-box to the .box above, how wide is the content region?
Answer and explanation
Answer: 156px
Under border-box, width refers to the whole box (content + padding + border), and the content is whatever is left.
200px − 20px×2 (left+right padding) − 2px×2 (border) = 156px
The whole box fits inside the 200px you specified.
Q3. How much space appears between the two paragraphs below?
.first { margin-bottom: 24px; }
.second { margin-top: 16px; }
<p class="first">Previous paragraph</p>
<p class="second">Next paragraph</p>
Answer and explanation
Answer: 24px
Vertical margins between adjacent siblings collapse. Both are positive, so the larger of the two — 24px — wins. It does not become 40px.
Making the parent display: flex with flex-direction: column disables collapsing, and the gap becomes 40px.
Q4. With a dashed border, the background color is visible through the gaps. Is this behavior specified?
Answer and explanation
Answer: Yes, this is specified.
The initial value of background-clip is border-box, so the background is painted out to the outer edge of the border. The border is drawn on top of the background, so with borders that have gaps like dashed or dotted, you see the background through the gaps.
If you don't want the background to show through, set background-clip: padding-box. The background stops at the outer edge of the padding and doesn't extend under the border.
Summary
- The box of an element is made of four nested regions, from the inside out: content → padding → border → margin
widthrefers to the content region alone by default (content-box); padding and border are added outsidebox-sizing: border-boxmakeswidthinclude the padding and border. Margins are not included- By default the background is painted out to the padding and border regions (
background-clip: border-box). It is not painted into the margin - Vertical margins collapse. It happens in three situations: adjacent siblings, parent with its first or last child, and an empty block
- Padding and margin can both be set individually on each side
- Tailwind CSS Guide — Spacing — Handling padding and margin with utility classes
- Tailwind CSS Guide — Sizing and positioning — Setting width and height
- MDN — Box model
- MDN — background-clip
- MDN — Mastering margin collapsing
What to read next
- Selectors and cascade — How the browser decides which style wins in the end