CSS Box Model Explained: Content, Padding, Border, Margin and box-sizing
Every element is four nested rectangles: content, padding, border, and margin. Understand how width is calculated in each box-sizing mode, why margin never counts toward an element's size, and when adjoining vertical margins collapse into one — then test yourself with six practice questions and full explanations.
The CSS box model describes every element on a page as four nested rectangles: the content box, wrapped by padding, wrapped by the border, wrapped by the margin. In the standard box model the width and height you write apply only to the content box, so padding and border are added on top of that number — which is exactly why a box you sized at 300px often measures wider than 300px on screen.
The four areas, from the inside out
- Content box — where your text, images, or child elements live. In the standard box model this is what
widthandheightsize. - Padding box — breathing room inside the border, set with
padding. The element's background paints through it, and padding can never be negative: negative values are invalid and the whole declaration is dropped. - Border box — the visible edge drawn by
border. This is the rectangle a user perceives as "the box." - Margin box — transparent space outside the border that pushes neighbours away. Margin is never part of the element's own size in either
box-sizingmode, and unlike padding it may be negative.
One useful outlier: outline is drawn outside the border but takes up no space at all, so it never shifts the layout. That is why focus rings are outlines rather than borders.
Two ways to measure: content-box vs border-box
The box-sizing property decides what your width number is measuring. It has two values you will use — content-box and border-box — and the initial value is content-box.
.card {
width: 300px;
padding: 20px;
border: 2px solid #333;
}
/* content-box (initial): rendered box = 300 + 20+20 + 2+2 = 344px */
.card { box-sizing: border-box; }
/* border-box: rendered box = 300px; content shrinks to 256px */
With width: 300px, padding: 20px, border: 2px | content-box | border-box |
|---|---|---|
| Content area | 300px | 256px |
| Padding and border | added outside the 300px | absorbed inside the 300px |
| Rendered border box | 344px | 300px |
| Margin | excluded | excluded |
With border-box, the declared width covers content + padding + border, and the content area absorbs the difference. If padding and border together exceed the declared width, the content box floors at 0 rather than going negative — you cannot shrink an element away with border-box. Because box-sizing is not inherited, most developers apply it globally with a *, *::before, *::after rule. Note that browser default stylesheets already use border-box for a handful of elements, including <table>, <select>, <button>, and several <input> types, so "the browser default" is not universally content-box.
Why block-direction margins collapse
Margin collapsing is the rule that surprises people. When the bottom margin of one in-flow block box touches the top margin of the next, the two do not add up — they collapse into a single margin equal to the larger of the two. A 40px bottom margin meeting a 24px top margin yields 40px of space, not 64px. Two margins count as adjoining only when both belong to in-flow block-level boxes in the same block formatting context and no line box, clearance, padding, or border separates them.
Collapsing also happens between a parent and its first in-flow child (top margins) when the parent has no top border, no top padding, and no inline content, and between a parent and its last in-flow child (bottom margins) when the parent additionally has no fixed height or min-height. An empty block with nothing to separate its own top and bottom margins collapses them together too. Collapsing occurs only in the block direction — vertically, in a standard horizontal writing mode. Horizontal margins never collapse.
When margins do not collapse
- Floated boxes: margins between a float and any other box do not collapse.
- Absolutely positioned boxes.
- Flex items and grid items — margins never collapse inside a
display: flexordisplay: gridcontainer. - A box that establishes a new block formatting context (for example
display: flow-rootoroverflow: hidden) does not collapse its margins with its own in-flow children. - Inline-level and inline-block boxes.
Ready to practice? Work the questions below, then keep going with the WGU D276 Web Development Foundations study guide or more D276 practice questions.
Practice: Css Box Model
-
A <div> is styled with the rules below, and no box-sizing is declared anywhere in the stylesheet: .card { width: 300px; padding: 20px; border: 2px solid #333; margin: 10px; } How much horizontal space does the element's visible box (the border box) occupy?
- 300px
- 304px
- 344px
- 364px
Show answer & explanation
Correct answer: 344px. With no box-sizing declared, the initial value content-box applies, so width sizes only the content area and you add both paddings and both borders: 300 + 20 + 20 + 2 + 2 = 344px. The tempting wrong answer is 364px, which also adds the 10px margins — but margin sits outside the border box and is never counted as part of the element's size in either box-sizing mode.
-
You keep the same declarations and add box-sizing: border-box: .card { box-sizing: border-box; width: 300px; padding: 20px; border: 2px solid #333; } How wide is the content box?
- 256px
- 260px
- 300px
- 344px
Show answer & explanation
Correct answer: 256px. With border-box, the declared width of 300px covers content + padding + border, so the content area is what is left over: 300 − 40 (padding) − 4 (border) = 256px. Choosing 300px is the common slip — that is the width of the whole border box, not of the content inside it.
-
Two sibling paragraphs are in normal flow in the same block formatting context, one directly after the other, with no border or padding between them. The first has margin-bottom: 40px and the second has margin-top: 24px. How much vertical space separates them?
- 24px
- 32px
- 40px
- 64px
Show answer & explanation
Correct answer: 40px. Adjoining margins of in-flow block-level boxes in the same block formatting context collapse into a single margin equal to the larger of the two, so the gap is 40px. The trap is 64px, which assumes the margins stack additively; additive stacking is what horizontal margins do, and horizontal margins never collapse, but in the block direction the larger value simply wins.
-
A <div> has no padding, no border, no inline content, and no height set. Its first in-flow child is a <p> with margin-top: 32px. The 32px gap appears above the div instead of inside it. Which single change keeps that space inside the parent?
- Add padding-top: 1px to the div
- Add margin-top: 0 to the div
- Add a height to the div
- Give the div the same margin-top: 32px as the child
Show answer & explanation
Correct answer: Add padding-top: 1px to the div. A parent's top margin collapses with its first in-flow child's top margin unless the parent has a top border, top padding, or inline content, or the child has clearance — so even 1px of padding-top separates the edges and the space renders inside the div. Adding a height is the tempting choice, but height and min-height affect only whether the parent's bottom margin collapses with the last child's; they do nothing at the top edge. Setting margin-top: 0 on the div does not help either, since the collapsed margin becomes max(0, 32px) and still escapes.
-
A containing block is 600px wide and 300px tall, in a standard horizontal writing mode. A block-level child inside it declares padding-top: 10%. How large is that top padding?
- 10px, since percentages on padding fall back to a pixel equivalent
- 30px, because it resolves against the containing block's height
- 60px, because it resolves against the containing block's width
- It depends on the height of the child's content
Show answer & explanation
Correct answer: 60px, because it resolves against the containing block's width. Percentage padding on every side — including padding-top and padding-bottom — resolves against the width of the containing block, so 10% of 600px is 60px. The tempting answer is 30px, which assumes vertical padding tracks the container's height; it never does, and that width-based behaviour is exactly what made the classic padding-top percentage trick for fixed aspect ratios work.
-
Which pair of margins will actually collapse into a single margin?
- The bottom margin of an in-flow block box and the top margin of the block sibling directly after it, in the same block formatting context, with no border, padding, or line box between them
- The right margin of a block box and the left margin of the box beside it
- The top margins of two adjacent flex items inside a flex container
- The bottom margin of a floated box and the top margin of the block below it
Show answer & explanation
Correct answer: The bottom margin of an in-flow block box and the top margin of the block sibling directly after it, in the same block formatting context, with no border, padding, or line box between them. Two margins are adjoining only when both belong to in-flow block-level boxes participating in the same block formatting context and nothing separates them, which describes the first option exactly. Margins never collapse inside a flex or grid container, margins between a floated box and any other box do not collapse, and horizontal margins never collapse at all — so the right/left pair simply adds up.
A worked example: the three-column row that overflows
Here is the bug that teaches this concept faster than any diagram. You want three equal cards across a 900px container:
.card {
width: 33.3333%;
padding: 16px;
border: 1px solid #ccc;
float: left;
}
Each card's content box is about 300px, but the rendered border box is 300 + 32 + 2 = 334px. Three of those is 1002px, which does not fit in 900px, so the third card drops to a new line. The fix is one declaration, not a recalculation of the percentages:
*, *::before, *::after { box-sizing: border-box; }
Now 33.3333% is the rendered width, padding and border eat into the content area, and the row fits. This is why so many modern stylesheets and CSS frameworks open with that reset — and why box-sizing needs the universal selector plus the pseudo-element selectors: the property is not inherited, and * does not match ::before or ::after on its own.
Mistakes people actually make
- Counting margin as part of the width. Neither
box-sizingmode includes margin. If you need the total footprint an element claims in a row, you add margins yourself, on top of the border box. - Expecting adjoining vertical margins to add. Two 20px margins between stacked in-flow blocks give you 20px, not 40px. Teams sidestep the whole question by setting margins in one direction only — for example
margin-bottom(or its logical equivalentmargin-block-end) on every block and zero on top. - Using
outlineandborderinterchangeably. A border changes layout; an outline occupies no space, which is why it is the safe choice for focus rings and for debugging without shifting anything. - Assuming vertical percentage padding follows height. It follows the containing block's width.
- Trying to use negative padding. Negative padding values are invalid; only margins can be negative.
How to reason about the tricky cases
When spacing looks wrong, ask two questions in order. First: what is my width actually measuring? Open DevTools, look at the computed box diagram, and compare the content number to the number you typed. If they differ, you are in content-box.
Second: is a margin escaping? If a gap appears outside a container rather than inside it, a child's margin has collapsed through the parent. Anything that separates the two edges stops it — top padding, a top border, or inline content. So does making the parent establish a new block formatting context with display: flow-root or overflow: hidden, since such a box does not collapse margins with its in-flow children. Turning the parent into a flex or grid container also stops it, because margins never collapse inside a flex or grid container. That is one quiet reason modern layouts feel more predictable than float-based ones.
For negative margins, the rule is arithmetic rather than magic: the collapsed margin is the largest positive margin plus the most negative one. A 30px bottom margin adjoining a −10px top margin leaves 20px of space. When every adjoining margin is negative, the result is simply the most negative of them.
References: MDN: Introduction to the CSS box model and W3C CSS 2.2, section 8.3.1: Collapsing margins.
Want someone to walk you through this?
Book 1-on-1 prep for WGU D276 — original coaching, never exam content.
Stuck on this topic? WhatsApp us on +1 646 980 4914.
Working through the whole course? Read the full WGU D276 study guide, or see every WGU D276 practice topic.