The CSS Box Model: Margin, Border, Padding, and Content

- The CSS Box Model in One Sentence
- The Four Layers, Explained
- Margin vs. Padding: The Difference That Actually Matters
- box-sizing: The Single Most Useful Line of CSS
- Margin Collapsing: Why Your Vertical Spacing Looks Wrong
- Inline Elements Play by Different Rules
- Debugging With the Box Model
- Putting It Together
The CSS Box Model in One Sentence
Every element on a web page is a rectangular box, and the CSS box model describes how the browser calculates that box's total size from four layers: the content, the padding around it, the border around that, and the margin outside everything. Understand those four layers and one property (box-sizing), and most "why is this element the wrong size?" mysteries disappear.
Here is the model from the inside out:
| Layer | What it is | Grows the box? | Has a background? |
|---|---|---|---|
| Content | The text, image, or child elements | Set by width/height |
Yes |
| Padding | Clear space inside the border | Yes | Yes (element's bg shows through) |
| Border | The line around the padding | Yes | It is the visible edge |
| Margin | Clear space outside the border | Pushes neighbors away | No — always transparent |
The order never changes: content sits in the middle, padding wraps it, border wraps the padding, and margin is the empty moat on the outside. A background color or image fills the content and padding, stops at the border, and never bleeds into the margin.
The Four Layers, Explained
Content
The content box holds whatever the element contains. Its dimensions come from width and height (or, if you set neither, from the content itself and the element's display type). For a block element with no explicit width, the content box stretches to fill its parent.
Padding
Padding is breathing room inside the box. Because the element's background extends through the padding, it's what you reach for when you want space between text and the edge of a button or card without the background stopping short.
.button {
padding: 12px 20px; /* 12px top/bottom, 20px left/right */
}
Padding accepts one to four values (top, right, bottom, left — clockwise), or you can target one side with padding-top, padding-inline, and friends. Padding can never be negative.
Border
The border draws a visible line between padding and margin. Its shorthand takes a width, a style, and a color:
.card {
border: 2px solid #d0d0d0;
}
A border only renders if you give it a style (solid, dashed, dotted, etc.). border-width alone does nothing without a style. Border width counts toward the box's rendered size, which matters for the box-sizing discussion below.
Margin
Margin is transparent space outside the border that pushes other elements away. Unlike padding, margin can be negative (margin-top: -10px pulls an element upward), and it does not carry the element's background.
Margin also has two behaviors that trip people up: margin: 0 auto centers a block element horizontally, and vertical margins collapse — a topic worth its own section below.
Margin vs. Padding: The Difference That Actually Matters
Both add space, so which do you use? The reliable test:
- Use padding when the space should share the element's background, respond to clicks, or sit inside a border. Button interiors, card interiors, and clickable link areas are padding jobs.
- Use margin when the space should separate the element from its neighbors and stay transparent. Gaps between stacked cards, space under a heading, or centering a container are margin jobs.
| Question | Margin | Padding |
|---|---|---|
| Inside or outside the border? | Outside | Inside |
| Shows the element's background? | No | Yes |
| Can be negative? | Yes | No |
| Counts as clickable area? | No | Yes |
| Collapses with neighbors? | Yes (vertical) | Never |
A concrete example: to make a link's entire padded area clickable and give it a hover background, pad it. To space that link away from the next one, add margin. If you had used margin for the interior gap, the background would stop at the text and the extra space wouldn't register clicks.
For a full breakdown of the length units you'll plug into these properties — when to use px, rem, em, or % — see our guide to CSS units.
box-sizing: The Single Most Useful Line of CSS
Here's the classic surprise. You set a width of 300px, add padding and a border, and the element renders wider than 300px:
.box {
width: 300px;
padding: 20px;
border: 5px solid black;
/* Rendered width = 300 + 20 + 20 + 5 + 5 = 350px */
}
By default (box-sizing: content-box), width sizes only the content box. Padding and border are added on top, so your 300px box occupies 350px. Multiply that across a grid and layouts overflow their containers.
The fix is box-sizing: border-box, which makes width include padding and border:
.box {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 5px solid black;
/* Rendered width = 300px. Content shrinks to 250px to make room. */
}
Now the box is exactly the width you asked for, and padding and border eat into that width instead of stacking onto it. This is so much more predictable that nearly every modern codebase applies it globally:
*,
*::before,
*::after {
box-sizing: border-box;
}
Drop that at the top of your stylesheet and width starts meaning what you expect. border-box is supported in every browser in use today, so there's no compatibility reason to avoid it.
content-box (default) |
border-box (recommended) |
|
|---|---|---|
width applies to |
Content only | Content + padding + border |
A 300px box with 20px padding + 5px border renders at |
350px | 300px |
| Adding padding later | Grows the box | Shrinks the content |
| Best for | Legacy quirks | Predictable layouts |
Note that margin is never included in either mode — it always sits outside the declared width. A 300px border-box element with 10px of horizontal margin still occupies 320px of horizontal space in its container.
Margin Collapsing: Why Your Vertical Spacing Looks Wrong
Vertical (block-direction) margins between elements don't add up the way you'd expect. Instead, the larger of two adjacent margins wins and the smaller is absorbed. This is called margin collapsing.
.top { margin-bottom: 30px; }
.bottom { margin-top: 20px; }
/* Gap between them is 30px, NOT 50px */
The browser uses the larger margin (30px) and discards the overlap. Collapsing happens in three situations:
- Adjacent siblings — the gap between two stacked elements collapses to the larger margin.
- Parent and first/last child — a child's top margin can escape its parent and push the parent down, unless a border, padding, or
overflowother thanvisiblesits between them. - Empty blocks — an empty element's own top and bottom margins collapse together.
Key rules to remember:
- Collapsing affects vertical margins only. Horizontal margins never collapse.
- Padding and borders do not collapse — they always add. If you want guaranteed, additive spacing, padding is the safer tool.
- Flexbox and Grid items do not collapse their margins, which is one reason modern layouts feel more predictable.
If margin collapsing is fighting you, common fixes are switching the container to display: flex and using the gap property, adding a single padding or border to the parent, or simply applying margin in one direction only (many developers use margin-top everywhere, or margin-bottom everywhere, but not both).
Inline Elements Play by Different Rules
The box model applies to every element, but inline elements (like <span> and <a> by default) treat it selectively:
widthandheightare ignored on inline elements.- Vertical padding and margin are applied visually but don't push surrounding lines apart — the padding can overlap neighboring text.
- Horizontal padding and margin work normally.
If you need full box-model control on an inline element — a link styled as a button, say — promote it with display: inline-block (keeps it in the text flow but respects width/height) or display: block. This is exactly what button-style links do.
Debugging With the Box Model
Every browser's DevTools shows a live box-model diagram. Right-click an element, choose Inspect, and look at the Computed tab (Chrome, Edge, Firefox) for a color-coded rectangle: content in blue, padding green, border yellow, margin orange. Hover each layer and the browser highlights it on the page. When an element is "too big" or spacing looks off, this diagram tells you instantly which layer is responsible — usually a padding you forgot or a margin that collapsed.
A quick visual-debugging trick during layout work:
* {
outline: 1px solid rgba(255, 0, 0, 0.3);
}
outline is deliberately used here instead of border because — unlike border — outline doesn't affect the box model or layout. It draws on top without shifting anything, so you can see every box's edges without changing their sizes. Remove it before shipping.
Putting It Together
The box model is the foundation the rest of CSS layout stands on. Once the four layers and box-sizing: border-box are second nature, the properties that place those boxes on the page — Flexbox, Grid, and positioning — become far easier to reason about, because you already know exactly how big each box is and where its edges fall.
From here, two natural next steps: if you're still building your base, our beginner's guide to CSS sets the broader context, and once you're sizing boxes confidently, learning how to center a div puts margins, padding, and the box model to work in the layout task everyone eventually needs.
A short checklist to keep the box model working for you:
- Add
box-sizing: border-boxglobally sowidthbehaves. - Reach for padding for interior space, margin for space between elements.
- Expect vertical margins to collapse — use padding or
gapwhen you need guaranteed spacing. - Remember margin is always outside the declared width and never shows a background.
- Use DevTools' box-model diagram before guessing which layer is wrong.