Himanshu SharmaSoftware engineer
Let’s talk

CSS · Lesson 12 of 29

box-sizing

Learn why width plus padding can overflow a layout, how box-sizing border-box fixes it, and the one-line reset most modern stylesheets start with.

10 minThe box modelUpdated 18 October 2026

By the end of this lessonExplain the difference between content-box and border-box, predict an element's real width under each, and apply the standard reset.

The problem

You have a container 400px wide and want a box inside it to fill the width, with a little padding. So you write:

css
.box { width: 100%; padding: 20px; border: 2px solid; }

…and the box sticks out of its parent by 44px. You did nothing wrong; you ran into how CSS measures boxes by default.

content-box: the default

By default, width and height describe only the content area. Padding and border are added on top. This is called box-sizing: content-box:

text
visible width = width + padding-left + padding-right + border-left + border-right

So a width: 300px box with 20px padding and a 2px border is 300 + 40 + 4 = 344px wide. Try it:

html
<style>
  .box {
    width: 300px;
    padding: 20px;
    border: 2px solid #7c3aed;
    background: #ede9fe;
    margin-bottom: 12px;
  }
  .border-box { box-sizing: border-box; }
</style>
<div class="box">content-box (default): 344px wide in total</div>
<div class="box border-box">border-box: exactly 300px wide</div>

The second box is exactly as wide as you asked for. The text area inside it shrinks to make room for the padding and border.

border-box: what you actually want

With box-sizing: border-box, width and height include the content, the padding and the border:

text
visible width = width   (always)
content width = width - padding - border

That matches how people think: "this card is 300 pixels wide." Add padding or a border later and the card stays 300px. A column that is 50% wide with padding stays 50% wide.

Margin is outside both models and is never included.

The reset almost every project uses

Rather than set it on one box at a time, apply it to everything at the top of the stylesheet:

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

The * selector matches every element, and the two pseudo-elements are included because * does not match them. Put this first, before other rules. A slightly more flexible version sets html { box-sizing: border-box; } and *, *::before, *::after { box-sizing: inherit; }, which lets a third-party widget opt out. Either is fine.

Try the fix in a realistic case:

html
<style>
  * { box-sizing: border-box; }
  .wrapper { width: 300px; border: 2px dashed #6b7280; padding: 0; }
  .inner { width: 100%; padding: 20px; background: #dcfce7; }
</style>
<div class="wrapper">
  <div class="inner">100% wide with padding: no overflow now.</div>
</div>

Remove the first rule and watch .inner spill out of the dashed box.

What it does and does not change

  • It changes how width, height, min-* and max-* are measured.
  • It does not change padding, border or margin themselves.
  • Form controls (inputs, buttons, selects) already use border-box in most browsers, which is part of why people can feel they behave differently from div boxes.
  • Images and other replaced elements follow the same rule.

Why this became the standard

Early on, designers did sums to keep layouts consistent: "the column is 300 minus 40 padding minus 4 border, so I set 256." Switching to border-box removes the sums and makes percentages behave. It is one of the first lines in nearly every CSS framework and reset, and in this site's own stylesheet.

Common mistakes

  • Forgetting the reset and chasing overflow bugs with random negative margins.
  • Applying border-box only to some elements, giving inconsistent sizes.
  • Expecting margin to be included.
  • Using width: 100% with horizontal margin, which still overflows. Use auto width on blocks where you can.
  • Mixing both models in one layout without realising it.

Exercise

Make two boxes sit in a 600px-wide container, each 50% wide, with 20px padding and a 2px border. They should fit side by side with no wrapping. (Hint: use display: inline-block or float, plus the reset.)

Show one possible answer
html
<style>
  * { box-sizing: border-box; }
  .row { width: 600px; font-size: 0; }
  .col { display: inline-block; width: 50%; padding: 20px; border: 2px solid #4f46e5; font-size: 16px; vertical-align: top; }
</style>
<div class="row">
  <div class="col">Left</div><div class="col">Right</div>
</div>

font-size: 0 on the row removes the small gap that whitespace between inline-block boxes creates. You will see cleaner ways with Flexbox soon.

Key points

  • By default (content-box), width and height set only the content area, so padding and border make the box bigger.
  • With border-box, width and height include padding and border, so the box is exactly the size you set.
  • Setting a width of 100 percent plus padding with content-box overflows its parent, which is a very common bug.
  • Most stylesheets start with a rule that sets border-box on every element.
  • Margin is never included in either model.

Check yourself

1. With box-sizing: border-box, width: 300px and padding: 20px on each side, how wide is the visible box?
2. What is the default value of box-sizing?
3. A div has width: 100% and padding: 16px under content-box. What happens?
4. Does box-sizing: border-box include margin in the width?

Free tools for this lesson