Skip to main content

📦 The Box Model in Depth

Every element on a page is a rectangular box. The box model describes the four layers that make up that box and how their sizes combine — and it is the single most important idea for building predictable layouts. Get comfortable here and Flexbox, Grid, and everything after will make far more sense.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Name the four box-model layers — content, padding, border, margin — and what each controls
  • Explain how box-sizing: border-box changes size calculations and why it is the sane default
  • Predict margin collapsing and know how to prevent it
  • Size elements with width/height, min/max, and aspect-ratio
  • Handle content that doesn't fit using the overflow family of properties

Estimated Time: 40–50 minutes  •  Difficulty: Beginner

Hands-on: Build a card component and prove you can predict its exact rendered width.

In This Lesson

What Is the Box Model?

In CSS, every element is a box — even a single word inside a <span>. The box model defines how much space that box takes and how its layers nest. Once you can picture the box, unexpected gaps and stubborn widths stop being mysteries.

📦 A shipping analogy: the content is the item, the padding is the bubble wrap around it, the border is the cardboard box, and the margin is the empty space you leave between this box and the next one on the shelf.

The Four Layers

From the inside out: content, then padding, then border, then margin. Each is its own concentric layer.

The four box-model layers Nested rectangles show margin on the outside, then border, then padding, then the content area in the centre. margin border padding content
Figure 1 — The four layers. Backgrounds paint across the content and padding; the border sits just outside the padding; the margin is transparent space beyond the box.
graph TD A[Element box] --> B[Content: width, height] A --> C[Padding: inner space, cannot be negative] A --> D[Border: width, style, color, radius] A --> E[Margin: outer space, can be negative, can collapse]

Padding

padding: 20px;                 /* all four sides */
padding: 10px 20px;            /* top/bottom | left/right */
padding: 10px 20px 15px 25px;  /* top | right | bottom | left (clockwise) */
padding-inline: 1rem;          /* logical: left & right in LTR */

Padding is inside the border, is covered by the element's background, and is part of the clickable area. It cannot be negative.

Border

border: 2px solid var(--border-color);        /* width | style | color */
border-radius: 8px;                            /* rounded corners */
border-radius: 50%;                            /* a circle, on a square box */
border-block-end: 3px dashed hotpink;          /* one logical edge */

Margin

margin: 16px;
margin: 0 auto;        /* horizontal centring for a block with a set width */
margin-top: -8px;      /* negative margins pull an element toward its neighbour */

Unlike padding, margin can be negative, and vertical margins can collapse — a quirk covered in its own section below.

box-sizing: the Big One

Here is the single most useful thing in this lesson. By default (content-box), the width you set applies to the content only — padding and border are added on top, making the box bigger than you asked for.

/* Default: content-box */
.a {
  box-sizing: content-box;
  width: 200px;
  padding: 20px;
  border: 5px solid;
}
/* Rendered width = 200 + 20 + 20 + 5 + 5 = 250px  😖 */

/* border-box: width INCLUDES padding and border */
.b {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 5px solid;
}
/* Rendered width = exactly 200px  😊 */
content-box versus border-box With content-box a 200px width plus padding and border renders 250px wide; with border-box the same declarations render exactly 200px because padding and border are drawn inside the declared width. content-box → 250px rendered width:200 border-box → 200px rendered width:200 (incl. pad+border)
Figure 2 — With border-box, the number you type is the number you get. This is why almost every codebase resets to it globally.

✅ The universal reset

Put this at the top of your stylesheet and never fight surprise widths again:

*, *::before, *::after {
  box-sizing: border-box;
}

border-box makes percentage widths, padding, and borders compose predictably — indispensable for responsive layouts.

Margins & Collapsing

The most surprising box-model behaviour is margin collapsing: when two vertical margins meet, they don't add up — they merge into a single margin equal to the larger of the two.

.top    { margin-bottom: 20px; }
.bottom { margin-top: 30px; }
/* The gap between them is 30px, NOT 50px */

The rules

  1. Only vertical margins collapse; horizontal margins never do.
  2. Adjacent siblings collapse to the larger of the two margins.
  3. A parent and its first/last child can collapse together if nothing (padding, border, or content) separates them.

💡 How to stop a collapse

Insert something between the margins: a sliver of padding or a border on the parent, or switch the container to a flex or grid context — margins never collapse inside those. In modern layouts, many developers sidestep the issue entirely by using gap instead of margins.

⚠️ Negative margins are a sharp tool

Negative margins genuinely pull elements out of flow (useful for overlaps and bleed effects), but they make layouts hard to reason about. Prefer gap, transform: translate(), or positioning when you can.

Width, Height & Aspect Ratio

Dimensions accept absolute lengths, percentages (of the parent), viewport units, and intrinsic keywords.

.box {
  width: 60%;            /* of the parent's content width */
  max-width: 640px;      /* but never wider than this */
  min-height: 200px;     /* at least this tall, grow with content */
  height: auto;          /* let content decide — the usual choice */
}

/* Viewport and intrinsic sizing */
.full  { width: 100vw; height: 100vh; }
.snug  { width: fit-content; }    /* as wide as content, up to available space */
.tight { width: min-content; }    /* as narrow as the longest unbreakable word */

✅ Sizing best practices

  • Prefer max-width over a fixed width so content can shrink on small screens.
  • Avoid fixing height on text containers — let content set it and use min-height if you need a floor.
  • Reach for relative units (%, rem, vw) for responsive behaviour.

aspect-ratio

The modern aspect-ratio property locks a width-to-height ratio, which is perfect for media and uniform cards — no more padding-hack.

.video  { width: 100%; aspect-ratio: 16 / 9; }  /* height follows automatically */
.avatar { width: 64px;  aspect-ratio: 1;      } /* a perfect square */

Overflow Handling

When content is bigger than its box, overflow decides what happens.

overflow: visible;  /* default — content spills outside the box */
overflow: hidden;   /* extra content is clipped away */
overflow: scroll;   /* scrollbars always shown */
overflow: auto;     /* scrollbars appear only when needed */

/* Axis-specific */
overflow-x: auto;
overflow-y: hidden;
ValueClips?ScrollbarsTypical use
visibleNoNoneDefault flow
hiddenYesNoneCropping, preventing layout breaks
scrollYesAlwaysReserving scroll space to avoid layout shift
autoYesOnly if neededChat panes, code blocks, fixed-height regions

Truncating text

Combine overflow with text properties for the classic ellipsis. A single line needs three properties; multi-line uses line-clamp:

.one-line {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.three-lines {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

The Box Model in Layouts

The box model doesn't disappear when you adopt modern layout systems — it underpins them.

LayoutHow the box model applies
Normal flowBlock boxes stack; vertical margins collapse; margin: 0 auto centres.
FlexboxNo margin collapsing; box-sizing affects how flex-basis is measured; use gap for spacing.
GridItems fill cells; padding/border still count inside the cell; gap replaces inter-item margins.

💡 Debugging box-model issues

Open your browser's DevTools and inspect an element — the box-model diagram shows exact content, padding, border, and margin values. For a quick visual audit, temporarily outline everything:

* { outline: 1px solid red; }  /* outline, not border — it won't shift layout */

Hands-on Exercise

🏋️ Predict-the-Width Card

Objective: Build a card and prove you can calculate its rendered size under both box-sizing models.

Instructions:

  1. Create a .card with width: 300px, padding: 24px, and border: 2px solid.
  2. First set box-sizing: content-box and calculate the rendered width by hand, then verify in DevTools.
  3. Switch to box-sizing: border-box and calculate again. Note which one matched your width declaration.
  4. Add a heading and a paragraph, then use margin to space them — and observe whether their vertical margins collapse.
  5. Bonus: add a circular avatar with aspect-ratio: 1 and border-radius: 50%.
💡 Hint

Rendered width in content-box = width + left/right padding + left/right border. In border-box, padding and border are subtracted from the width, so the outer size stays put.

✅ Answer

content-box: 300 + 24 + 24 + 2 + 2 = 352px rendered.
border-box: exactly 300px rendered (content area shrinks to 300 − 24 − 24 − 2 − 2 = 248px).

.card {
  box-sizing: border-box;
  width: 300px;
  padding: 24px;
  border: 2px solid var(--border-color);
  border-radius: 8px;
}
.card .avatar {
  width: 56px;
  aspect-ratio: 1;
  border-radius: 50%;
}

🎯 Quick Quiz

Question 1: With box-sizing: content-box, an element has width: 200px, padding: 20px, and border: 5px solid. What is its rendered width?

Question 2: Two stacked block elements have a 30px bottom margin and a 20px top margin respectively. How much space sits between them?

Question 3: Which overflow value shows scrollbars only when content actually overflows?

Summary & Quiz

🎉 Key Takeaways

  • Every element is a box with four layers: content, padding, border, margin.
  • box-sizing: border-box makes the declared width the rendered width — reset it globally.
  • Vertical margins collapse to the larger value; padding, borders, and flex/grid contexts prevent it.
  • Prefer max-width and min-height over fixed dimensions; use aspect-ratio for media.
  • overflow: auto adds scrollbars only when needed; combine overflow with text properties to truncate.

📚 Further Reading

🚀 What's Next?

With the box model solid, we go back to selectors and get precise: Attribute and Pseudo-class Selectors — targeting elements by their attributes and states.

🎉 Boxed up!

You can now predict any element's size and spacing. This foundation carries straight into Flexbox and Grid.