The CSS Box Model Explained for Beginners
Every element on a web page is a rectangular box. This guide explains the four layers of that box — content, padding, border, and margin — and the box-sizing fix that makes them sane.
What you'll learn
- ✓The four layers of every CSS box
- ✓How content, padding, border, and margin combine to form size
- ✓Why `box-sizing: border-box` is the standard fix
- ✓How margins collapse between adjacent elements
- ✓The difference between block and inline display
Prerequisites
- •A working knowledge of CSS — see What is CSS?
Every element on a web page is a rectangle. That sentence sounds simple, but it is the single most important fact in all of CSS. Headings, paragraphs, images, links, even the page itself — all rectangles. Once you understand how those rectangles are sized and spaced, layout stops being mysterious.
This post explains the CSS box model — the rule that defines those rectangles.
The four layers
Every box on a page has four layers, working outward from the content:
- Content — the actual text, image, or child elements inside the box.
- Padding — clear space between the content and the border.
- Border — a line drawn around the padding.
- Margin — clear space outside the border, separating the box from its neighbors.
A diagram in text:
+-----------------------------+ <- margin edge
| margin |
| +---------------------+ | <- border edge
| | border | |
| | +--------------+ | | <- padding edge
| | | padding | | |
| | | +----------+ | | | <- content edge
| | | | content | | | |
| | | +----------+ | | |
| | +--------------+ | |
| +---------------------+ |
+-----------------------------+
When you open the Elements panel in Chrome or Firefox developer tools and hover an element, the browser highlights these layers in different colors. That panel is the fastest way to internalize the model — peek at it often.
Writing the layers in CSS
Each layer has its own property:
.card {
width: 300px;
padding: 20px;
border: 2px solid steelblue;
margin: 16px;
}
That gives every element with class="card":
- A content area 300 pixels wide.
- 20 pixels of padding on all four sides.
- A 2-pixel solid border around the padding.
- 16 pixels of margin on all four sides.
You can target individual sides:
.card {
padding-top: 20px;
padding-right: 16px;
padding-bottom: 20px;
padding-left: 16px;
}
Or use the shorthand, which accepts one to four values:
.card {
padding: 20px; /* all four sides */
padding: 20px 16px; /* top/bottom, then left/right */
padding: 20px 16px 12px; /* top, left/right, bottom */
padding: 20px 16px 12px 8px; /* top, right, bottom, left — clockwise */
}
The same rules apply to margin and border-width.
The classic sizing surprise
Here is the gotcha that trips up every beginner. Consider this:
.card {
width: 300px;
padding: 20px;
border: 2px solid black;
}
How wide is the element on the page?
You might say 300 pixels. The browser, by default, says 344 pixels — 300 + 20 + 20 + 2 + 2. The width property only sets the content width. Padding and border are added on top.
This default behavior is called the content-box model. It is rarely what you actually want. You wanted a 300-pixel card, not a 344-pixel one.
The box-sizing: border-box fix
Modern CSS gives you an alternative model called border-box, where width includes the padding and border:
.card {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid black;
}
Now the box is exactly 300 pixels wide on the page. The padding and border eat into that 300 pixels rather than being added to it. The content area shrinks accordingly.
This is so much more intuitive that almost every modern stylesheet starts with:
*,
*::before,
*::after {
box-sizing: border-box;
}
That single rule applies border-box to every element on the page. You only need to write it once. Most CSS frameworks and reset stylesheets include it.
Try it yourself. Create a <div> with width: 200px, padding: 20px, and a 5-pixel border. Inspect it in the browser’s developer tools and confirm the total width is 250 pixels. Add box-sizing: border-box and watch the total shrink to exactly 200 pixels.
Margin and padding are different
Padding is inside the border; margin is outside it. The visible consequences:
- A background color fills the content and padding, but stops at the border. Margin is always transparent.
- A click on padded space hits the element. A click on margin does not.
- Padding pushes the content inward; margin pushes neighbors away.
This is the most common practical distinction:
.card {
background: white;
padding: 1rem; /* white background extends here */
margin: 1rem; /* empty space, neighbors pushed away */
}
If you want a colored gap, use padding. If you want a transparent gap, use margin.
Collapsing margins
Margins between two vertically adjacent block elements combine in a way that surprises every beginner — they collapse into a single margin equal to the larger of the two.
<h2>Heading</h2>
<p>Paragraph</p>
h2 {
margin-bottom: 32px;
}
p {
margin-top: 16px;
}
You might expect a 48-pixel gap between them. The actual gap is 32 pixels, not 48. The browser takes the larger of the two adjoining vertical margins and discards the smaller one.
Collapsing only applies to vertical margins between block elements. Horizontal margins never collapse, and modern layout tools — Flexbox and Grid — disable the behavior altogether. That is one more reason to use them, which we cover in the next post.
Block vs. inline
Boxes come in two main flavors, controlled by the display property.
Block elements take up the full width of their parent and start on a new line. Examples: <div>, <p>, <h1>, <section>. You can set width, height, padding, and margin on all four sides.
Inline elements sit on the same line as their neighbors and only take up as much width as their content needs. Examples: <a>, <span>, <strong>, <em>. You cannot set width or height on them, and vertical margin is ignored.
You can change the default with display:
a.button {
display: inline-block;
padding: 0.5rem 1rem;
background: steelblue;
color: white;
}
inline-block is the best of both worlds: the element sits inline like text but accepts width, height, and padding like a block. It is how buttons styled from <a> tags traditionally work.
The full set of display values is large, but four cover most cases: block, inline, inline-block, and none (which removes the element entirely from the page).
A worked example
Here is a card component built using everything in this post:
<article class="card">
<h2 class="card__title">CSS Box Model</h2>
<p class="card__body">
Every element on a web page is a rectangle. Master the box model
and layout stops being mysterious.
</p>
<a href="#" class="card__link">Read more</a>
</article>
*,
*::before,
*::after {
box-sizing: border-box;
}
.card {
width: 320px;
padding: 1.5rem;
margin: 1rem;
border: 1px solid #ddd;
border-radius: 0.5rem;
background: white;
}
.card__title {
margin: 0 0 0.5rem;
font-size: 1.25rem;
}
.card__body {
margin: 0 0 1rem;
line-height: 1.6;
color: #444;
}
.card__link {
display: inline-block;
padding: 0.5rem 1rem;
background: steelblue;
color: white;
border-radius: 0.25rem;
text-decoration: none;
}
Read the stylesheet slowly. Every property either sizes a box, sets its inner spacing, or sets the gap to its neighbors. There is nothing else happening.
Try it yourself. Build the card above. Then add a second card next to it. Without changing the HTML, give the cards a 24-pixel gap between them using only margin. Open the browser inspector and confirm the gap is exactly 24 pixels.
A practical workflow
When a layout misbehaves — usually the spacing is wrong or an element is the wrong size — the steps are always the same:
- Open the browser’s developer tools.
- Click the element in the Elements panel.
- Look at the highlighted box model on the right.
- Identify which layer is too big or too small.
- Adjust the corresponding property in your stylesheet.
This loop becomes muscle memory within a week of practice. Every working front-end developer relies on it dozens of times a day.
Recap
You now know:
- Every element on a page is a rectangular box
- A box has four layers: content, padding, border, margin
- By default
widthsets only the content, butbox-sizing: border-boxmakes it include padding and border - Margin is transparent and outside the border; padding is filled by the background
- Vertical margins between block elements collapse to the larger of the two
- Block, inline, and inline-block are the three display modes you use most often
Next steps
The box model tells you how each element occupies space. The next post tackles how multiple boxes line up next to each other — Flexbox, the modern tool for one-dimensional layout.
→ Next: CSS Flexbox: A Practical Beginner’s Guide
Questions or feedback? Email codeloomdevv@gmail.com.