CSS Box Model
Table of Contents
Every element on a web page is a rectangular box. Whether it’s a heading, a paragraph, or a button — the browser wraps it in a box with four layers: content, padding, border, and margin. This is the CSS Box Model, and understanding it is essential for controlling layout and spacing.
If you’ve been through the CSS Introduction, you’ve already styled elements with colors and fonts. Now we’ll look at how those elements take up space on the page.
The Four Layers
Here’s what makes up every element’s box, from inside out:
- Content — the actual text, image, or child elements
- Padding — space between the content and the border
- Border — a line around the padding
- Margin — space between this element and neighboring elements
.card {
width: 300px;
padding: 20px;
border: 2px solid #333;
margin: 16px;
}
With default box sizing, the total width of this element is 300 + 20 + 20 + 2 + 2 + 16 + 16 = 376px. The width property only sets the content area — padding, border, and margin are added on top.
Seeing the Box Model
Open your browser’s DevTools (F12), select any element, and look at the box model diagram. It shows the exact pixel values for content, padding, border, and margin. This is the fastest way to debug spacing issues.
Padding
Padding creates space inside the border, between the border and the content. It’s useful for giving text breathing room inside a container.
/* All four sides */
.box { padding: 20px; }
/* Vertical | Horizontal */
.box { padding: 10px 20px; }
/* Top | Right | Bottom | Left (clockwise) */
.box { padding: 10px 20px 10px 20px; }
/* Individual sides */
.box {
padding-top: 10px;
padding-right: 20px;
padding-bottom: 10px;
padding-left: 20px;
}
Here’s a visual comparison:
<div class="no-padding">No padding</div>
<div class="with-padding">With padding</div>
<style>
.no-padding, .with-padding {
background: #e0f0ff;
border: 2px solid #3388cc;
margin-bottom: 8px;
}
.with-padding {
padding: 20px;
}
</style>
The text in .with-padding sits comfortably away from the border, while .no-padding has text pressed right against it.
Border
Borders sit between padding and margin. They have three properties: width, style, and color.
/* Shorthand: width style color */
.box { border: 2px solid #333; }
/* Individual properties */
.box {
border-width: 2px;
border-style: solid;
border-color: #333;
}
/* One side only */
.box { border-bottom: 3px dashed #999; }
Common border styles: solid, dashed, dotted, double, none.
Border Radius
border-radius rounds the corners of an element. It’s technically not part of the box model, but it’s used alongside borders constantly:
.rounded { border-radius: 8px; }
.pill { border-radius: 9999px; }
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
}
Margin
Margin creates space outside the border, pushing other elements away. The syntax mirrors padding:
/* All sides */
.box { margin: 16px; }
/* Vertical | Horizontal */
.box { margin: 16px 24px; }
/* Center a block element horizontally */
.box {
width: 600px;
margin: 0 auto;
}
The margin: 0 auto pattern is one of the most common in CSS — it centers a fixed-width block element within its parent.
Margin Collapse
Vertical margins between adjacent block elements collapse — only the larger margin is used, not the sum of both. This is one of CSS’s most surprising behaviors:
.top { margin-bottom: 20px; }
.bottom { margin-top: 30px; }
The gap between .top and .bottom is 30px, not 50px. The larger margin wins.
box-sizing: border-box
By default, width and height only set the content area. Padding and border are added on top, making elements wider than you’d expect. This is content-box sizing.
border-box changes this so that width and height include padding and border:
/* Default behavior */
.content-box {
box-sizing: content-box;
width: 300px;
padding: 20px;
border: 2px solid #333;
/* Total width: 300 + 20 + 20 + 2 + 2 = 344px */
}
/* border-box behavior */
.border-box {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid #333;
/* Total width: 300px (content shrinks to 256px) */
}
Almost every modern project applies border-box globally because it makes sizing predictable:
*, *::before, *::after {
box-sizing: border-box;
}
box-sizing. This is one of the most common CSS debugging moments.
Display and the Box Model
How the box model behaves depends on the element’s display type.
Block elements (div, p, h1–h6) take up the full width available and stack vertically. All box model properties work as expected.
Inline elements (span, a, strong) sit within a line of text. Vertical padding and margin don’t push other elements away — they overlap.
/* This won't work as expected on a span */
span {
margin-top: 20px; /* ignored */
padding-top: 20px; /* visible but doesn't affect layout */
width: 200px; /* ignored */
}
Inline-block gives you the best of both: the element sits inline but respects all box model properties:
span {
display: inline-block;
width: 200px;
padding: 10px;
margin: 8px;
/* All of these now work */
}
Practical Example: Card Component
Let’s put it all together by building a card component — one of the most common UI patterns:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Card Component</title>
<style>
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, sans-serif;
background: #f5f5f5;
display: flex;
justify-content: center;
padding: 40px;
}
.card {
width: 350px;
background: white;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.card-image {
width: 100%;
height: 200px;
background: #3388cc;
}
.card-body {
padding: 24px;
}
.card-body h2 {
margin: 0 0 8px 0;
font-size: 1.25rem;
}
.card-body p {
margin: 0 0 16px 0;
color: #666;
line-height: 1.5;
}
.card-button {
display: inline-block;
padding: 10px 20px;
background: #3388cc;
color: white;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
}
</style>
</head>
<body>
<div class="card">
<div class="card-image"></div>
<div class="card-body">
<h2>Card Title</h2>
<p>A simple card component built with the CSS box model. Padding, borders, and margins working together.</p>
<button class="card-button">Learn More</button>
</div>
</div>
</body>
</html>
Every spacing decision in this card uses the box model:
padding: 24pxon.card-bodygives the text breathing roommargin: 0 0 8px 0on the heading creates space below it without extra space aboveborder-radius: 8pxwithoverflow: hiddenrounds the card corners and clips the imageborder-boxsizing means the card is exactly350pxwide, no surprises
What’s Next
The box model controls how individual elements take up space. The next step is learning how to arrange multiple elements together with CSS Flexbox — a layout system that makes centering, spacing, and responsive design much easier.