The Box Model
📦 Chapter 3 — The Box Model
Every single element on a webpage — a heading, a paragraph, an image, a button — is rendered by the browser as a rectangular box. The box model describes the four layers that make up that box and how they interact to determine the element's final size and spacing. Understanding the box model is not optional; it is the foundation every layout decision in CSS is built on. Get it wrong and nothing ever lines up the way you expect.
1 — The Four Layers
Every box is composed of four concentric layers, from the inside out: content, padding, border, and margin.
width and height.2 — Padding
Padding creates space inside the element, between its content and its border. It inherits the element's background colour, so it appears as part of the element visually.
/* Set each side individually */
.box {
padding-top: 16px;
padding-right: 24px;
padding-bottom: 16px;
padding-left: 24px;
}
/* Shorthand — one to four values */
.box { padding: 16px; } /* all four sides: 16px */
.box { padding: 16px 24px; } /* top+bottom: 16px | left+right: 24px */
.box { padding: 8px 16px 24px; } /* top: 8px | sides: 16px | bottom: 24px */
.box { padding: 8px 16px 24px 32px; } /* top right bottom left (clockwise) */
The shorthand order — clockwise from top
3 — Border
The border wraps the padding and content. It has three components: width (thickness), style (the line type), and colour. All three must be set — a border with no style is invisible.
/* Shorthand — width | style | colour */
.box { border: 2px solid #4f8ef7; }
/* Longhand — set each property separately */
.box {
border-width: 2px;
border-style: solid;
border-color: #4f8ef7;
}
/* Target individual sides */
.card {
border: 1px solid #2a2d3a; /* thin border all around */
border-left: 4px solid #7ecfa0; /* thick accent on the left */
}
/* Rounded corners */
.pill {
border-radius: 999px; /* fully rounded (pill shape) */
}
.card {
border-radius: 6px; /* subtly rounded corners */
}
Border style values
| Value | Appearance | Common use |
|---|---|---|
solid | Continuous line | Most common — cards, inputs, dividers |
dashed | Dashes with gaps | Drop zones, placeholders, "add item" areas |
dotted | Dots with gaps | Decorative, focus rings |
double | Two lines with a gap | Decorative headings |
none | No border | Removing browser default borders on buttons/inputs |
border-radius to round the corners of an element's background even if it has no border. It clips the background (and any padding) to the rounded shape.
4 — Margin
Margin creates space outside the element, pushing other elements away. Unlike padding, margin is always fully transparent — it never takes the background colour of the element.
/* Individual sides */
.box {
margin-top: 20px;
margin-right: 0;
margin-bottom: 20px;
margin-left: 0;
}
/* Same as above — shorthand: top+bottom 20px, sides 0 */
.box { margin: 20px 0; }
/* auto — centres a block element horizontally */
.container {
width: 800px;
margin: 0 auto; /* top+bottom: 0 | sides: auto (equal) */
}
/* Negative margins — pull elements closer together */
.overlap {
margin-top: -20px; /* overlaps 20px with the element above */
}
margin: 0 auto is one of the most-used CSS patterns — the standard way to horizontally centre a fixed-width block element on the page.Margin collapse
One surprising behaviour: when two vertical margins touch — the bottom margin of one element and the top margin of the element below it — the browser does not add them together. Instead, it uses only the larger of the two. This is called margin collapse.
.box-a { margin-bottom: 20px; }
.box-b { margin-top: 20px; }
/* Gap between .box-a and .box-b is 20px, not 40px */
/* If box-a had margin-bottom: 30px, the gap would be 30px */
5 — Width and Height
The width and height properties set the size of the content area — the innermost layer of the box. The element's rendered size on the page also includes padding and border on top of this.
.box {
width: 300px; /* fixed width */
height: 200px; /* fixed height */
}
/* Constrain with min/max — useful for responsive designs */
.article {
width: 100%; /* fills the parent */
max-width: 700px; /* but never wider than 700px */
min-width: 280px; /* and never narrower than 280px */
}
/* Heights are often best left unset — let content decide */
/* min-height is safer than height for variable content */
.hero {
min-height: 400px;
}
height on elements with variable content can cause text to overflow the box. Prefer min-height when you want a minimum size but need the box to grow with its content.6 — box-sizing: The Critical Setting
By default, when you set width: 300px, the browser applies that 300px to the content area only. Padding and border are then added on top, making the element wider than 300px. This is called content-box sizing and is the source of countless layout bugs.
padding: 20px (each side)
border: 2px (each side)
padding: 20px (each side)
border: 2px (each side)
With box-sizing: border-box, padding and border are included in the declared width. What you set is what you get — the element is exactly as wide as you said.
/* Apply border-box sizing to every element on the page */
*,
*::before,
*::after {
box-sizing: border-box;
}
::before and ::after ensures the setting applies to CSS-generated pseudo-elements too. This reset is so universally useful that it is included in virtually every CSS framework and starter template.content-box default was a design mistake from the early web. Every professional CSS codebase starts with the border-box reset. Make it a habit: first line of every stylesheet, before anything else.
7 — Calculating Total Element Size
Even with border-box set, you still need to account for margin when thinking about how much space an element occupies in the layout flow. Margin sits outside the box and always adds to the space the element takes up relative to its neighbours.
.card {
box-sizing: border-box;
width: 300px; /* the box is exactly 300px wide */
padding: 20px; /* included in the 300px */
border: 2px solid #4f8ef7; /* included in the 300px */
margin: 16px; /* OUTSIDE the 300px */
}
/* Box width: 300px (border-box — padding + border absorbed) */
/* Total space in layout: 300 + 16 + 16 = 332px horizontally */
8 — Inspecting the Box Model in DevTools
Every browser's developer tools include a visual box model inspector. When you click an element in the Elements panel, a diagram shows its exact content, padding, border, and margin values — colour-coded identically to the diagram at the top of this chapter.
- Chrome/Edge: Elements panel → select an element → scroll down in the Styles panel to find the box model diagram, or switch to the "Computed" tab.
- Firefox: Inspector panel → select an element → "Box Model" section in the right panel.
- Safari: Elements panel → select an element → "Computed" tab → Box Model section at the top.
content-box sizing problem. Guessing wastes time — inspect first.
9 — Quick Reference
| Property | What it controls | Key values |
|---|---|---|
padding | Inner space (content → border) | px, rem, %, auto — uses shorthand clock order |
border | Border around padding+content | width style color e.g. 2px solid red |
border-radius | Corner rounding | px, %, 50% = circle, 999px = pill |
margin | Outer space (pushes other elements) | px, rem, %, auto — same shorthand as padding |
width | Content width (or total width with border-box) | px, %, auto, 100% |
height | Content height | px, %, auto — prefer min-height for variable content |
max-width | Upper width limit | px, % — commonly used with width: 100% |
box-sizing | Whether padding/border are included in width | border-box (use always) / content-box (avoid) |
✏️ Exercises
Start every exercise stylesheet with the box-sizing: border-box reset. Use your browser's DevTools box model inspector to verify your results — compare what you see on screen to what the inspector reports.
<div> with a fixed width of 400px and a fixed height of 200px. Give it a solid 3px border in a colour of your choice, 24px of padding on all sides, and 40px of margin at the top and bottom. Add a background colour so you can clearly see the padding area. Open DevTools and verify the box model matches what you set.box-sizing: border-box reset at the top of your stylesheet. The box model inspector in DevTools should show exactly 400px width and 200px height.* { box-sizing: border-box; }
.demo-box {
width: 400px;
height: 200px;
border: 3px solid #4f8ef7;
padding: 24px;
margin: 40px 0;
background-color: #1a2e1a;
}
<div> with class="alert". It should have: 12px top/bottom padding and 24px left/right padding, a 4px left-only solid border in a warning colour (orange or yellow), a lightly tinted background to match the border colour, no top or bottom margin, and text that reads "⚠️ Your session will expire in 10 minutes."padding: 12px 24px for the two-value shorthand. Use border-left: 4px solid #e8a87d and a very faint matching background like #2a1e0a.* { box-sizing: border-box; }
.alert {
width: 100%;
padding: 12px 24px;
border-left: 4px solid #e8a87d;
background-color: #2a1e0a;
color: #e8a87d;
margin: 0;
font-family: system-ui, sans-serif;
}
<div class="article"> that is 100% wide up to a maximum of 680px, centred horizontally on the page using margin: 0 auto, with 40px of padding on all sides. Give the page body a dark background and the article a slightly lighter background so the centring is visible. Put a few paragraphs of text inside so you can see the padding in action.max-width: 680px combined with width: 100% and margin: 0 auto is the classic centred-column pattern. The body needs a min-height: 100vh or enough content to show the background.* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background-color: #0d0d0d;
font-family: Georgia, serif;
padding: 40px 20px;
}
.article {
width: 100%;
max-width: 680px;
margin: 0 auto;
padding: 40px;
background-color: #1a1d27;
border-radius: 8px;
color: #e2e4ec;
line-height: 1.75;
}
content-box and border-box. Create two <div> elements side by side, both with width: 300px, padding: 20px, and border: 4px solid. Apply box-sizing: content-box to the first and box-sizing: border-box to the second. Give each a different background colour. Use DevTools to confirm the content-box element is wider than 300px, while the border-box element is exactly 300px.display: inline-block or float: left to place the boxes side by side (or just stack them vertically — the comparison still works). Inspect each in DevTools and compare the rendered widths..content-box-demo {
box-sizing: content-box;
width: 300px;
padding: 20px;
border: 4px solid #f08080;
background-color: #2e1a1a;
margin-bottom: 16px;
color: #f08080;
font-family: system-ui, sans-serif;
}
.border-box-demo {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 4px solid #7ecfa0;
background-color: #1a2e1a;
color: #7ecfa0;
font-family: system-ui, sans-serif;
}
<div class="content-box-demo">content-box: set 300px, renders as 348px</div>
<div class="border-box-demo">border-box: set 300px, renders as 300px</div>
The content-box element renders at 348px (300 + 20 + 20 padding + 4 + 4 border). The border-box element is exactly 300px. Same CSS width, very different result — this is why the reset matters.