Frontend Development · Tutorial 2 of 5
The CSS Box Model: margin, padding and borders without the confusion
By the FUTEAC Team · 27 October 2026 · 10 min read · Beginner
In short
Every HTML element is a box made of four layers: content in the middle, padding around the content, a border around the padding, and margin outside the border. By default, the width you set applies to the content only, so padding and border are added on top. box-sizing: border-box fixes that — it counts padding and border inside the width.
- Four layers, always in this order: content → padding → border → margin. There are no exceptions to the order.
- Default (
content-box): width = content only. Padding and border are added on top of the width you set. border-box: width = content + padding + border. The width you set is the width you get — the behaviour most beginners expect.- Margin is the space *between* boxes; padding is the space *inside* a box. Mixing them up is the most common beginner error.
- This tutorial feeds the HTML & CSS Foundations course (/course/html-css-foundations) and the CSS skill (/skill/css).
Before you start
What are the four parts of the box?
Every element on a page — a heading, a paragraph, a card — is a box with four layers, one inside the next:
| Layer | What it is | Does it show? |
|---|---|---|
| Content | The actual text or image inside the element | Yes — this is the visible part |
| Padding | Space between the content and the border, inside the element | Yes — it takes the element's background colour |
| Border | A line around the padding | Yes — you set its width, style and colour |
| Margin | Space outside the border, between this box and its neighbours | No — it is always transparent |
The order never changes: content is always in the middle, margin is always on the outside. If you remember nothing else, remember that.

Padding and margin take one, two or four values — one value sets all four sides, two values set top/bottom then left/right, four values set top, right, bottom, left, clockwise from the top:
.card {
padding: 20px; /* 20px on all four sides */
padding: 10px 20px; /* 10px top and bottom, 20px left and right */
padding: 10px 20px 30px 40px; /* top, right, bottom, left */
margin: 16px;
border: 2px solid #0f766e; /* width, style, colour */
}Expected result: 20px between text and edge, 16px of clear space outside, and a 2px solid teal border.
Why is my element wider than the width I set?
It has one cause: by default, the width you set applies to the content box only. Padding and border are added on top of it.
Take a card with these rules:
.card {
width: 300px;
padding: 20px;
border: 2px solid #0f766e;
}The browser's maths, with the default content-box:
- Content: 300px (the width you set)
- Padding: 20px left + 20px right = 40px
- Border: 2px left + 2px right = 4px
- Total rendered width: 300 + 40 + 4 = 344px
You asked for 300px and got 344px. The element is not broken — the default is doing exactly what it was designed to do, and what it was designed to do is unintuitive. Two cards at width: 50% with any padding overflow their row for the same reason — how most beginners first meet this problem. The same rule applies to height: height: 200px with padding: 20px and a 2px border renders 244px tall.
How does `box-sizing: border-box` fix it?
box-sizing: border-box changes what width means: the width you set now includes padding and border, and the content area shrinks to fit inside it.
.card {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid #0f766e;
}Now the maths is: total width 300px (exactly what you set), padding + border 44px, and a content area of 300 − 44 = 256px.
| `content-box` (default) | `border-box` | |
|---|---|---|
width: 300px means | Content is 300px | The whole box is 300px |
With padding: 20px + border: 2px | Renders 344px wide | Renders 300px wide |
| Content area | 300px | 256px |
Two width: 50% boxes with padding | Overflow the row | Fit the row |
Because border-box behaves the way people expect, it is standard practice to set it on everything:
*,
*::before,
*::after {
box-sizing: border-box;
}That rule is the first thing the HTML & CSS Foundations course adds to every stylesheet. margin is never included in either calculation — it always sits outside the box.
When should I use margin, and when padding?
The rule of thumb: padding is space inside the box, margin is space between boxes.
- Use padding when the space should be part of the element — inside its background and border. A button's text needs padding so it does not touch the edge, and the padding is clickable: clicking it still clicks the button.
- Use margin for space between two separate elements — the gap between two cards, or between a heading and the paragraph below it. Margin is transparent and never clickable.
A quick test: if the gap should take the element's background colour, it is padding; if it should stay the page background, it is margin.
What is margin collapsing — and why do my vertical gaps look wrong?
Two block elements stacked vertically do not add their margins together — the bigger margin wins and the smaller one disappears. This is called margin collapsing, and it is built into CSS, not a bug.
<p class="first">First paragraph.</p>
<p class="second">Second paragraph.</p>.first { margin-bottom: 20px; }
.second { margin-top: 30px; }Expected result: the gap is 30px, not 50px — the 30px margin absorbs the 20px one. The same thing happens between a parent and its first child: a child's top margin can "leak" out and push the parent down instead.
The fix that covers almost every case: set margins in one direction only — margin-bottom on every item in a list, never margin-top. If a child's margin is leaking out of its parent, adding padding or a border to the parent stops the collapse.
How do I see the box model in DevTools?
You do not have to guess the numbers — Chrome draws the box for you.
- Right-click the element and choose Inspect. The Elements panel opens with it highlighted.
- Hover over the element: Chrome overlays the box on the page — content in blue, padding in green, border in yellow, margin in orange.
- In the Styles pane, open the Computed tab: it shows a labelled box-model diagram with the exact pixel value of every layer.
Expected result: content 256px wide, padding 20px, border 2px, margin 16px — the same numbers as the diagram above.
Worked example: style one course card
Build a small course card — a title and one line of description. Save this as box-model-card.html and open it in Chrome.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Box model card</title>
<style>
* { box-sizing: border-box; }
body {
font-family: system-ui, sans-serif;
background: #f5f5f5;
padding: 24px;
}
.card {
width: 300px;
padding: 20px;
border: 2px solid #0f766e;
margin: 16px;
background: #ffffff;
border-radius: 8px;
}
.card h2 { margin: 0 0 8px; font-size: 20px; }
.card p { margin: 0; color: #444; }
</style>
</head>
<body>
<article class="card">
<h2>HTML & CSS Foundations</h2>
<p>Build your first real web pages with semantic HTML and modern CSS.</p>
</article>
</body>
</html>Walk through the numbers: border-box makes the total width exactly 300px; border and padding leave a content area of 300 − 40 − 4 = 256px wide. The margin: 16px sits outside the box. The heading's default margins are removed (margin: 0 0 8px) so the only space above the title is the card's own 20px of padding.
Expected result: a white card, 300px wide including its teal border, with 20px between text and border on every side. Change border-box to content-box, reload, and the card jumps to 344px wide — same code, same values, a different box. That one change is the whole lesson.
Try it yourself
Make a second card — same HTML, different class — with width: 300px, padding: 32px and border: 4px solid #b45309. Before reloading, work out on paper its total width and content width with border-box on, then check in the Computed tab. Then test yourself in the Module Quiz: CSS Styling on the HTML & CSS Foundations course page (/course/html-css-foundations).
Common mistakes
- Setting a width on a padded element without
border-box. Awidth: 100%box withpadding: 20pxoverflows its container by 40px. Add theborder-boxrule at the top of your stylesheet and the problem goes away everywhere at once. - Using margin where padding belongs. If the space should have the element's background — or be clickable, like the area around a button's text — it is padding. Margin is always transparent and never clickable.
- Expecting vertical margins to add up. Two stacked margins collapse to the larger one: 20px + 30px gives a 30px gap, not 50px. Set margins in one direction only (usually
margin-bottom). - Centring with
margin: 0 autoon an element with no width. Auto margins can only share out leftover space, and a block element with no width is already 100% wide — set awidthfirst, thenmargin: 0 autocentres it. - Forgetting the browser's default margins.
bodyhas an 8px margin and headings and paragraphs have their own. A gap you did not write is usually a default margin — inspect the element and read the Computed tab first.
Frequently asked questions
Does padding increase the clickable area of a button?
Yes. Padding is inside the element, so clicking the padded area around a button's text still clicks the button. Margin is outside the element and is never clickable.
What is the difference between margin and padding, in one sentence?
Padding is space inside the box, between the content and the border; margin is space outside the box, between this element and its neighbours.
Should I always use border-box?
For almost all real work, yes — it is the standard practice the HTML & CSS Foundations course uses. The default content-box still exists for compatibility, and you may meet it in older code — now you know how to read it.
Why is there a gap between my elements that I never set?
Almost always a default browser margin: body ships with an 8px margin, and headings and paragraphs have their own. Inspect the element — the Computed tab shows exactly which margin is responsible — and set it explicitly (margin: 0) rather than guessing.
Does the box model apply to inline elements like links?
Only partly. An inline element's horizontal padding and margin work normally, but its width and height are ignored, and vertical padding overlaps the lines above and below instead of pushing them apart. If you need a link to behave like a box, set display: inline-block. ---
Follow the Frontend Developer Roadmap
Build modern, responsive websites and web apps with HTML, CSS, JavaScript and React. Free, step by step, at your pace.
View the Roadmap