CSS・Size and the box model

Solving the mystery of the shifting width

You set width:300px, yet the box comes out bigger. It's because padding and border get added on the outside. One box-sizing lines everything up to the width you see.

You set width: 300px, yet the actual box is somehow a little bigger. The real culprit behind this mystery, which trips up so many people, is padding and borders being added on. Once you know how it works, box-sizing in a single word solves it.

Why does it get bigger?

Normally, CSS treats width as the width of the content only. Add padding (inner spacing) or border on top of that, and they get piled on the outside.

.box {
  width: 300px;
  padding: 20px;
  border: 5px solid teal;
}

With this, the actual width is “300 + 40 of left-and-right padding + 10 of left-and-right border = 350px.” It ends up a size larger than the 300 you specified.

width: 160px; is the same for both, yet content-box (left) is drawn a size larger by the amount of the padding and border, while border-box (right) stays exactly 160px.

Line them up with box-sizing

Here’s where box-sizing: border-box; comes in. Add it, and it calculates with padding and border included within the width.

.box {
  box-sizing: border-box;
  width: 300px;
  padding: 20px;
  border: 5px solid teal;
}

This way, no matter how much padding or border you add, the box’s width stays 300px. “The number you set = the size you see,” and layouts get much easier to build.

Another standard spell: resetting the look of lists

* (the asterisk) is a special selector that means “everything.” So * { box-sizing: border-box; } means “to all parts, all at once.”

In the same vein, there’s one more thing worth resetting up front. <ul> lists come with black dots and inner spacing by default.

ul {
  list-style: none;
  padding: 0;
}
The left keeps the default black dots and left spacing; the right, with list-style: none; and padding: 0;, has both the dots and spacing gone, looking clean.

list-style: none; removes the black dots, and padding: 0; removes the default spacing. When you want to use a list as a box, like for cards, wiping the “list-ness” clean with these two lines is the standard move.

With the same idea, <img> and <a> have standard resets as well.

img {
  max-width: 100%;
  display: block;
}
a {
  color: inherit;
}

max-width: 100%; (the tool you learned in width and height) is insurance so an image doesn’t spill out of its parent box. display: block; (the switch you learned in display) removes the slight gap that forms below an image. color: inherit; (the notation that came up with class selectors) is insurance to make a link whose color you haven’t decided yet the same color as the surrounding text, rather than blue. Both are resets that bring “parts you haven’t touched yet” into a quiet starting state.

Summary of this lesson

  1. width is normally the width of the content only (padding and border are added on the outside)
  2. box-sizing: border-box; makes it the width that includes them
  3. Much of “the width shifts / spills over” is solved by this
  4. list-style: none; padding: 0; resets a list’s black dots and spacing
  5. max-width: 100%; display: block; for img and color: inherit; for a are standard insurance

Try it: the page-wide spell, and resetting the favorites list

At the very top of the page, let’s write down the four spells.

* {
  box-sizing: border-box;
}
img {
  max-width: 100%;
  display: block;
}
a {
  color: inherit;
}
ul {
  list-style: none;
  padding: 0;
}

The black dots and spacing vanish from the <ul> of favorites (🎨 Drawing, 🍜 Ramen, 🎮 Games, 🐤 Shima).

Browser view. The black dots are gone from the “Favorites” list and the spacing removed, looking clean
Just removing the black dots brings it closer to looking like a “part” rather than a list.

With this, you can now control the size of your boxes exactly as you please.

FAQ

Where should I write box-sizing: border-box;?
You can write it on individual parts, but on most sites people write * { box-sizing: border-box; } once at the very top of the CSS to apply it to every part on the page.
Does border-box get rid of padding and border?
No. The look of padding and border stays the same — only the way it's calculated changes. It now calculates so that everything fits inside the size you set with width.
What if the width still shifts even after setting box-sizing?
Often there's another cause — a part where you forgot to put box-sizing: border-box; on *, or the parent element's own width simply isn't enough. First check that border-box is applied, then check the parent-child width relationship, in that order.