The Box Model
To the browser, every element on a page is a rectangle. Headings, paragraphs, images, buttons, even a single link: each one is a box. How big that box is, and how much space sits around it, is decided by the box model. Almost every layout problem you will meet ("why is this wider than I said?", "where did this gap come from?") is a box model question.
In this lesson you will learn the four layers of a box, how to set padding and margin, why box-sizing: border-box should be in every project, and the strange but useful rule called margin collapsing.
The four layers
From the inside out, every box has:
| Layer | What it is | Background shows? |
|---|---|---|
| Content | The text, image or child elements | Yes |
| Padding | Space between the content and the border | Yes |
| Border | A line around the padding (can be zero width) | Border colour |
| Margin | Space outside the border, pushing other boxes away | No, always transparent |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Box model</title>
<style>
body { font-family: system-ui, sans-serif; background: #f1f3f6; padding: 1rem; }
.card {
width: 16rem;
padding: 1.5rem;
border: 6px solid oklch(55% 0.14 250);
margin: 2rem;
background: white;
}
</style>
</head>
<body>
<div class="card">Priya's library card: valid until March 2027.</div>
<div class="card">A second card, pushed away by the margin.</div>
</body>
</html>The white background fills the content and padding areas. The blue border wraps around them. The margin is the grey space outside the border that keeps the two cards apart. Open the developer tools, select a card and look at the box model diagram in the Styles or Computed panel: it shows each layer with its exact size. It is the fastest way to answer "where does this space come from?".
Padding and margin shorthands
padding and margin accept one to four values. With four, they go clockwise from the top, like the hands of a clock: top, right, bottom, left.
.a { padding: 1rem; } /* all four sides */
.b { padding: 0.5rem 1rem; } /* top and bottom 0.5rem, left and right 1rem */
.c { padding: 1rem 1rem 2rem; } /* top 1rem, sides 1rem, bottom 2rem */
.d { margin: 0 auto 1rem 0; } /* top, right, bottom, left */
.e { margin-block-end: 1.5rem; } /* just the bottom, in logical form */
.f { padding-inline: 1.25rem; } /* left and right together */The last two lines use logical properties: block means the direction text lines stack (top to bottom in English) and inline means the direction text runs (left to right). They are explained in Logical Properties, and they are a good habit because they work for every language direction.
Padding can never be negative. Margins can: a negative margin pulls the element, or its neighbours, closer, and occasionally that is useful for overlapping effects.
box-sizing: the most useful reset in CSS
By default, width and height set the size of the content only. Padding and border are added on top. So in the example above, a card with width: 16rem, 1.5rem of padding on each side and a 6px border is actually 16 + 1.5 + 1.5 = 19rem, plus 12px, wide. That default is called box-sizing: content-box, and it makes sizes hard to plan.
With box-sizing: border-box, width and height include the padding and border. A box with width: 16rem is 16rem wide, full stop; the padding and border fit inside it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>box-sizing</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; }
.ruler { width: 300px; height: 8px; background: #e63946; margin-block: 0.5rem; }
.box { width: 300px; padding: 20px; border: 5px solid #1d3557; background: #e8eef7; }
.content-box { box-sizing: content-box; }
.border-box { box-sizing: border-box; }
</style>
</head>
<body>
<div class="ruler"></div>
<div class="box content-box">content-box: 300 + 40 + 10 = 350px wide</div>
<div class="ruler"></div>
<div class="box border-box">border-box: exactly 300px wide</div>
</body>
</html>The red bars are exactly 300px. The content-box box sticks out past its bar; the border-box box matches it. This is why nearly every modern style sheet starts with this rule:
*,
*::before,
*::after {
box-sizing: border-box;
}It applies border-box to every element and to ::before and ::after pseudo-elements. Put it at the very top of your CSS (or in a reset layer, see Cascade Layers) and sizes will mean what they say.
Centring a block with auto margins
When a block element has a width smaller than its parent, auto margins on the left and right share the leftover space equally, which centres the box:
.page {
max-width: 60rem;
margin-inline: auto; /* same as margin-left: auto; margin-right: auto; */
}This is the classic way to centre the main column of a website.
Margin collapsing
Here is a rule that surprises everyone once. When two block elements sit one above the other, their vertical margins do not add up. They collapse into a single margin, the size of the larger one.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Margin collapsing</title>
<style>
body { font-family: system-ui, sans-serif; padding: 1rem; }
.first { margin-bottom: 40px; background: #ffe8cc; padding: 0.5rem; }
.second { margin-top: 24px; background: #d8f3dc; padding: 0.5rem; }
.flex { display: flex; flex-direction: column; margin-top: 2rem; border-top: 2px dashed #999; }
</style>
</head>
<body>
<p class="first">margin-bottom: 40px</p>
<p class="second">margin-top: 24px. The gap above me is 40px, not 64px.</p>
<div class="flex">
<p class="first">Inside a flex container...</p>
<p class="second">...margins do not collapse, so this gap is 64px.</p>
</div>
</body>
</html>The first gap is 40px, the larger of the two margins. Inside the flex container, the same two paragraphs are 64px apart, because margins never collapse between flex or grid items.
The same thing can happen between a parent and its first or last child: a child's top margin can "escape" through the top of its parent. Padding or a border on the parent stops it, and so does display: flow-root, which you will meet in Display & Visibility.
Common mistakes
- Forgetting
border-box. Awidth: 100%box with padding overflows its parent. Add thebox-sizingreset. - Using padding for space between separate elements. Padding is inside the box (and takes the background). Use margin or
gapfor space between boxes. - Adding margins that should collapse, then being confused. Two vertical margins of 20px between paragraphs make a 20px gap, not 40px.
- Wrong shorthand order.
margin: 10px 20pxis top/bottom then left/right, not left/right first. - Expecting vertical margins on inline elements. Top and bottom margins have no effect on inline elements such as
<span>and<a>.
Key points
- Every element is a box made of content, padding, border and margin.
- Padding is inside the border and shows the background; margin is outside and is always transparent.
- Shorthands go clockwise from the top: top, right, bottom, left.
box-sizing: border-boxmakeswidthandheightinclude padding and border; apply it to every element.margin-inline: autocentres a block that has a width or max-width.- Vertical margins between blocks collapse to the larger one, but not inside flex or grid containers.
Exercise
Create two notice cards for a hostel in Pune. Add the box-sizing reset. Each card should be 20rem wide including its 1.25rem padding and 4px left border (use border-left), centred on the page with auto margins, with 1.5rem of space between the two cards. Check in the developer tools that each card is exactly 20rem wide.
Show solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hostel notices</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #f4f6f9; padding: 1rem; }
.notice {
width: 20rem;
padding: 1.25rem;
border-left: 4px solid oklch(55% 0.15 30);
background: white;
margin-inline: auto;
margin-block-end: 1.5rem;
}
</style>
</head>
<body>
<div class="notice">Water supply will be off on Sunday from 9 am to 1 pm.</div>
<div class="notice">Mess fees for November are due by the 5th.</div>
</body>
</html>With border-box, the padding and border fit inside the 20rem width, so the developer tools show 20rem for the whole card.
Quick Quiz
1. Which part of the box is always transparent?
Margin is outside the border and never shows the element's background.
2. A box has width: 200px, padding: 10px and border: 5px solid with the default box-sizing. How wide is it on screen?
With content-box, padding (2 x 10px) and border (2 x 5px) are added to the 200px content width.
3. Two stacked paragraphs have margin-bottom: 30px and margin-top: 20px. What is the gap between them?
Vertical margins between blocks collapse to the larger value.
4. What does padding: 1rem 2rem; set?
With two values, the first is for top and bottom and the second for the sides.
Learn CSS with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
