I have a code snippet element that I want to stretch to 100% of its parent. Easy peasy. Here's the code:
<div class="container">
<div class="box">
Code snippet
</div>
</div>
.container {
width: 400px;
border: 5px solid black;
margin: 10px;
}
.box {
background-color: #407AA4;
border: 3px solid red;
line-height: 100px;
color: #fff;
text-align: center;
width: 100%;
padding: 0 10px;
}
Wait! Why does it overflow like that? When we inspect the element we can see that its width is 426px meanwhile its parent is 400px. What is going on?
This, my friend, is a CSS box-sizing
problem. But before we fix it we need to understand why it happens. In order to do that first we need to make friends with CSS Box Model.
Box model
CSS Box Model is a way the browser represents each and every HTML element in the DOM Tree.
It consists of 4 layers, where the previous one is surrounded with the following one, just like the onion:
- content (blue) - changed by:
font-size
,line-height
,height
, etc. - padding (green) - changed by:
padding
,padding-left
,padding-top
, etc. - border (orange) - changed by:
border-width
- margin (brown) - changed by:
margin
,margin-left
,margin-top
, etc.
How can I see the Box Model of a given element?
Fortunately, every major browser has a way to visually represent the model in their DevTools, which we can open in a couple of steps:
- Hit
Ctrl + Shift + C
when in browser and click on the element of choice. - Inside opened DevTools in the
Elements
tab clickComputed
tab. - Bam. That's all.
- You can repeat from step 1 to pick a new element or just click the tag in the
Elements
tab DOM Tree.
The box-sizing
problem
Now that we know the basics we can say hi to the CSS box-sizing property. It can have one of 2 values:
- content-box (default)
- border-box
content-box
When we tell the browser that we want an element to have 100% width, like in our case, the browser:
- Gets the width of the parent, in our case 400px.
- Sets the elements content width to 400px.
- Adds 20px of padding (to left and right). Now width is 420px.
- Adds 6px of border (to left and right). Now width is 426px.
- Puts the element inside the parent.
Our calculation matches the width measured empirically.
How can we fix it?
border-box
The solution is to set the box-sizing: border-box
to the .box
element.
The browser now:
- Gets the width of the parent, in our case 400px.
- Sets the elements content width to 400px.
- Subtracts 20px of padding (to left and right). Now width is 380px.
- Subtracts 6px of border (to left and right). Now width is 374px.
- Puts the element inside the parent.
The steps remained almost the same, but in steps 3 and 4 instead of adding padding and border the browser now subtracts them.
If we take a look at the elements Box Model now we can see that the calculations checkout.
How to avoid this kind of problems in the future?
The very first thing I do at the beginning of every project is I add this piece of CSS code:
* {
box-sizing: border-box;
}
This selector applies border-box
value to every element in the DOM Tree, so that we don't have to worry this specific case anymore.
But be careful when you do this in your existing codebase, because all the layouts had been adjusted to the content-box
calculations and there is a high chance that something might break.
Conclusion
In this article we've made friends with CSS Box Model and box-sizing
property. We now know how the browser performs calculations regarding content-box
and border-box
properties. We've also learned what to do at the start of every project.
The full example can be explored here.
In the next articles we will get to know the lonely wanderer called quirk modes
and flirt with rendering layers concept.
See you around.