ESC

Type to search the knowledge base.

box-sizing border-box

Why border-box makes width include padding and border, the global reset pattern, and the layout bugs content-box still causes.

beginner3 min read
  • css
  • box-sizing
  • box-model

Ask for width: 200px with padding: 20px and border: 2px solid under the default content-box, and the border box becomes 244px wide. Under border-box, the 200px includes padding and border — the content area shrinks. That single switch is why almost every modern codebase sets box-sizing: border-box globally.

Docs: MDN box-sizing, MDN box model.

content-box vs border-box

.box {
  width: 200px;
  padding: 20px;
  border: 2px solid black;
}

.content-box {
  box-sizing: content-box; /* default */
  /* total outer width = 200 + 40 + 4 = 244px */
}

.border-box {
  box-sizing: border-box;
  /* total outer width = 200px; content = 200 - 40 - 4 */
}
Model width / height refers to
content-box Content area only
border-box Content + padding + border (not margin)

Margin is never inside width. Margin collapse and horizontal margin still sit outside the border box.

The global pattern

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

Or the inheritance trick:

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

The inheritance form makes it easy to opt a subtree back to content-box if a third-party widget assumes it (rare, but real).

Why product CSS wants border-box

.grid > * {
  width: 50%;
  padding: 1rem;
  border: 1px solid var(--border);
}

With content-box, two 50% columns + padding overflow the row. With border-box, percentages match how designers think: “half the row including padding.”

Form controls benefit the same way:

input,
select,
textarea,
button {
  font: inherit;
  box-sizing: border-box;
  width: 100%;
  padding: 0.5rem 0.75rem;
}

Worked example: equal cards

<div class="row">
  <article class="card">A</article>
  <article class="card">B</article>
</div>
.row {
  display: flex;
  gap: 1rem;
}

.card {
  box-sizing: border-box;
  flex: 1;
  min-width: 0;
  padding: 1.25rem;
  border: 1px solid #ddd;
}

flex: 1 already distributes space; border-box keeps borders from expanding past the flex line. Without it, adding a thicker border on hover can reflow neighbors.

What border-box does not fix

  • min-width: auto on flex/grid items — still need min-width: 0 for overflow.
  • Scrollable areas — height math still needs clear containing-block heights.
  • vh mobile toolbars — not a box-sizing issue.
  • Replaced elements — images use their own sizing rules; set max-width: 100%; height: auto.

Interview out-loud

“Default box-sizing is content-box, so width is only the content. border-box includes padding and border in the specified width, which matches how we usually design components and percentage layouts. I set it globally on * and pseudo-elements, and I still remember margin is outside and flex min-size can independently cause overflow.”

Footguns

  1. Mixing models in one component without noticing (third-party CSS).
  2. Expecting height: 100% + padding to “just work” without a defined parent height.
  3. Animating width while toggling padding — layout still thrashy; prefer transform for motion.
  4. Forgetting pseudo-elements in the reset — generated content uses the same model.
  5. Confusing border-box with “ignore padding” — padding still consumes space inside the width.

Further reading

Related guides