The box model

CSS · Essentials · 10 min

Spacing and sizing bugs almost always come from misunderstanding how these four layers add up.

The browser lays out every element as a rectangular box with four layers, from inside out:

  • content: the text or child elements, sized by width/height;
  • padding: space inside the border, which shows the element's background;
  • border: the visible edge;
  • margin: transparent space outside, pushing neighbours away.

By default (box-sizing: content-box) width sets only the content. A width: 300px box with padding: 20px and border: 1px takes up 342px. Almost every project switches to box-sizing: border-box, where width includes padding and border, so the box is exactly 300px.

Shorthands set four sides clockwise from the top: margin: 10px 20px means 10px top/bottom and 20px left/right. Prefer the logical properties margin-block (top/bottom in horizontal text) and margin-inline (left/right), plus padding-inline-start and friends, which also adapt to right-to-left languages.

margin: 0 auto centers a block that has a width: the auto margins split the free space.

One surprise: vertical margins between block elements collapse. Two paragraphs with margin: 20px are 20px apart, not 40px; the larger margin wins. Padding never collapses, and margins don't collapse inside flex or grid containers.

Open devtools and select an element: the box-model diagram shows each layer's exact size, which is the fastest way to debug spacing.

Example

*, *::before, *::after { box-sizing: border-box; }   /* the usual reset */

.card {
  width: 300px;              /* total width: exactly 300px with border-box */
  padding: 20px;
  border: 1px solid #ccc;
  margin-block: 16px;        /* top and bottom */
  margin-inline: auto;       /* centers the card horizontally */
}

p { margin-block: 1em; }     /* adjacent paragraphs: 1em apart, not 2em (collapse) */

.button { padding: 0.5rem 1rem; }  /* 0.5rem top/bottom, 1rem left/right */

Remember

  • content + padding + border + margin
  • box-sizing: border-box makes width include padding and border
  • margin-inline: auto centers a block with a width
  • Vertical margins between blocks collapse to the larger one

Watch out for

  • Adding padding to a width: 100% element with content-box and getting a horizontal scrollbar.

Check yourself

  1. With box-sizing: content-box, width: 200px, padding: 10px, border: 2px, what is the rendered width?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/CSS/Guides/Box_model/Introduction