Every box is a box
Content, padding, border, margin. Then box-sizing, which changes what the word "width" means, and margin collapsing, which is the last really weird thing in CSS.
Content, then padding around it, then border around that, then margin outside everything. Four rings. Padding is inside the background, margin is outside it, and that single fact decides which one you want about eighty per cent of the time, if you want the background to extend, it is padding.
By default, width sets the content box only. So width: 300px with padding: 20px and a 4px border occupies 348 pixels, and the layout you carefully calculated is 48 pixels too wide. This is such a reliable source of frustration that essentially every codebase on earth starts with *, *::before, *::after { box-sizing: border-box; }, which makes width mean the whole visible box, padding and border included.
The instrument below makes the difference physical. Under content-box, adding padding pushes the outer edge outward. Under border-box, the outer edge stays put and the content shrinks instead. Same declaration, opposite behaviour. Watch the dashed bracket move between the two regions and you will not need to memorise which is which.
Every box is a box
width 200 + padding 16+16 + border 2+2 = 236px on the page
+ margin 12+12 = 260px of horizontal space claimed · height 90 + 32 + 4 = 126px
.card {
box-sizing: content-box;
width: 200px;
height: 90px;
padding: 16px;
border: 2px solid;
margin: 12px;
}The default is content-box, where width describes the content and padding and border are added outside it. Add padding and watch which edge moves.
Then margin collapsing, which is the last really strange rule left in CSS. Two vertical margins that meet do not add up, the larger one wins. 30px meeting 20px produces a 30px gap, not 50. It happens between siblings, and it happens between a parent and its first or last child, where the child’s margin escapes the parent entirely and pushes the parent down instead. That second case is the source of the classic "why is there space above my container" bug.
Three things stop it, and knowing which one applies where is the actual skill. Padding or a border between the two margins stops it, because they no longer meet. A new block formatting context on the parent, overflow: hidden, display: flow-root, stops parent-child collapsing. And flex or grid containers do not collapse margins between their children at all, which is one of the quieter reasons modern layouts feel more predictable than the ones you inherit.
Note the trap in that list: overflow: hidden is the most cargo-culted fix in CSS and it only helps the parent-child case. Between two siblings it does nothing, and the instrument will let you try it and watch the gap refuse to move. Being wrong about that here is a great deal cheaper than being wrong about it at 6pm on a Friday.
Finally, open DevTools on any element and look at the box model diagram at the bottom of the Computed tab. Every number in it is live. When something is the wrong size, that diagram tells you which ring is responsible before you have read a single line of CSS.
You should now be able to
- Compute the rendered size of an element by hand
- Explain what border-box actually changes
- Predict when two margins collapse and when they do not
- Read the box model diagram in DevTools and act on it
Loading…