In short
box-sizing: border-box makes CSS width include padding and border, so boxes are the size you expect. Learn the width math problem and the universal box-sizing reset. The width math problem By default, CSS uses box-sizing: content-box. This means width only sets the size of the content.
box-sizing: border-box makes CSS width include padding and border, so boxes are the size you expect. Learn the width math problem and the universal box-sizing reset.
The width math problem
By default, CSS uses box-sizing: content-box. This means width only sets the size of the content. Padding and border are added on top.
.box {
width: 300px;
padding: 20px;
border: 5px solid black;
}
How wide is this box on screen? Not 300px. Let's do the math:
content-box (the default):
5px + 20px + 300px + 20px + 5px = 350px
border padding content padding border
The box is 350px wide. This causes real problems. Imagine two columns, each width: 50%, with some padding. Together they are wider than 100%, so the second one drops below the first. You'd need to calculate every width by hand.
The fix: box-sizing: border-box
With box-sizing: border-box, the width includes the content, padding and border. The browser makes the content area smaller to fit.
border-box:
total width = 300px
content = 300 - 20 - 20 - 5 - 5 = 250px
Here is a comparison you can try yourself:
<div class="box content-box">content-box</div>
<div class="box border-box">border-box</div>
.box {
width: 300px;
padding: 20px;
border: 5px solid #5e35b1;
margin-bottom: 10px;
background-color: #ede7f6;
}
.content-box {
box-sizing: content-box;
}
.border-box {
box-sizing: border-box;
}
Both boxes have the same CSS width, but the first one is visibly wider (350px) than the second (300px). The border-box one is exactly the size you asked for. That's why it feels natural: when you say 300px, you get 300px.
Note: Margin is never included in the width, in either mode. Margin is space outside the box.
The universal box-sizing reset
Because border-box is so much easier, almost every modern website starts its stylesheet with this small snippet:
*,
*::before,
*::after {
box-sizing: border-box;
}
The * selects every element. *::before and *::after are pseudo-elements, extra boxes that CSS can create; you'll meet them later, and the reset includes them so they behave the same way. Put this at the very top of your styles.css, and every box on your page will use the simple math.
You will see this snippet in nearly every CSS framework and starter template. It is safe to use on every project.
Where border-box really helps: a form input
Here's a realistic case: a full-width input in a signup form.
<form class="signup">
<label for="email">Email</label>
<input type="email" id="email" placeholder="you@example.com">
</form>
*,
*::before,
*::after {
box-sizing: border-box;
}
.signup {
max-width: 400px;
padding: 20px;
border: 1px solid #ccc;
}
.signup input {
display: block;
width: 100%;
padding: 12px;
border: 2px solid #999;
border-radius: 4px;
}
The input fills the form exactly, with nice padding inside. Without the reset, width: 100% plus 12px padding and 2px border on each side would make the input 28px too wide, and it would stick out past the form's edge.
Common mistake: Putting the reset in the middle or at the end of a big stylesheet. Keep it as the very first rule in your file, so it's easy to find and every later rule can build on it.
Practice exercise
Make a container with max-width: 500px. Inside it, put a heading and a <textarea> with width: 100%, padding: 16px and a 3px border. First, try it without the reset and notice that the textarea pokes out of the container on the right. Then add the universal reset at the top of your CSS and watch it fit perfectly.
Hint: give the container a visible border too, so you can clearly see where its edge is.
Key takeaways
- By default (
content-box),widthdoes not include padding and border. box-sizing: border-boxincludes padding and border inside thewidth.- Margin is never part of the width.
- Start every project with the universal
box-sizing: border-boxreset.