You write width: 200px, add a little padding and a border, and the box on screen comes out 250 pixels wide. Then two boxes that should sit side by side drop onto separate lines. Nothing is broken: CSS is following a rule called the box model. Once you see it, a whole category of "why is this too wide?" bugs disappears, and one line of CSS makes most of them go away for good.
When a browser draws a web page, it treats every element (a paragraph, a button, an image, a <div>) as a rectangle. CSS (Cascading Style Sheets, the language that controls how HTML looks) lets you size that rectangle, and it's built from four layers, nested like the rings of an onion:
Here is a typical rule that sets all four. A px is a CSS pixel, the standard unit for sizes on screen:
.card {
width: 200px;
padding: 20px; /* on all four sides */
border: 5px solid orange; /* thickness, style, colour */
margin: 20px; /* on all four sides */
}
So how wide is the card? Most people guess 200px. The browser says 250px.
By default, CSS applies width to the content area only. Padding and border are then added on both sides, left and right:
200 content
+ 40 padding (20 left + 20 right)
+ 10 border ( 5 left + 5 right)
= 250px the box you can see
The margin isn't in that 250, because margin is invisible. But it still takes up room: the card needs 250 + 20 + 20 = 290px of horizontal space before the next thing can sit beside it.
This default behaviour has a name: box-sizing: content-box. The setting box-sizing decides which layer the width measures, and almost every element starts with content-box (a few form controls such as buttons are exceptions). Play with the sliders and watch the numbers. Then flip the switch at the top.
Box model playground
The readout's last line, browser measured, isn't calculated by this page's maths. It asks the browser how wide it actually drew the box (a value JavaScript calls offsetWidth), so you can see the formula and the real result agree.
An extra 50 pixels might sound harmless. It stops being harmless the moment you size things relative to their container. Two classic cases:
width: 50%. Half plus half is the full width. Add any padding or border and each column is now more than half, so the second one doesn't fit and drops to the next line.width: 100%. You want it to fill its container exactly. Give it padding and a border (inputs almost always have them) and it pokes out past the right edge.Try both. The dashed outline is the parent element, the container the boxes are supposed to fit inside.
Layout lab
Notice what happens at padding 0: everything fits again, because there's nothing to add. That's why this bug shows up late. A layout works fine until someone adds a bit of padding to make it look nicer.
A box with no width set is fine. If you leave width alone, a block element like a <div> or <p> automatically fills its container, and its padding and border fit inside that space. The surprise only happens when you set an explicit width (or height) on something that also has padding or border.
box-sizing: border-boxWith box-sizing: border-box, width measures from the outside of the border instead. The box is exactly as wide as you said, and the browser squeezes the padding and border inside that width, making the content area smaller to compensate:
200px width you asked for = the box you see
− 40 padding
− 10 border
= 150px left for the content
Most developers find this far easier to think about: "this card is 200 pixels wide" means what it says. It's so popular that nearly every modern project starts its stylesheet with this rule, which switches every element on the page over:
*, *::before, *::after {
box-sizing: border-box;
}
The * is the universal selector: it matches every element. ::before and ::after are pseudo-elements, little extra boxes CSS can generate before or after an element's content; they aren't matched by * alone, so they're listed separately. Popular CSS frameworks such as Bootstrap and Tailwind include this rule for you.
Two things border-box does not change:
width, under either setting.width: 60px with 40px of padding on each side, there's no room left for content, so the content area becomes 0 and the box ends up wider than 60px anyway. (Try it in the playground: border-box, width 60, padding 40.)So far every side got the same value. padding and margin also take two, three or four values, and the order trips people up:
padding: 10px; /* all four sides */
padding: 10px 20px; /* top+bottom 10, left+right 20 */
padding: 10px 20px 30px; /* top 10, left+right 20, bottom 30 */
padding: 10px 20px 30px 40px; /* top, right, bottom, left */
The four-value version goes clockwise from the top: top, right, bottom, left. You can also target one side with padding-left, margin-top and so on. For width, only the left and right values count, so padding: 10px 20px adds 40px to a content-box element's width, not 20.
One handy margin trick: margin: 0 auto on a block element that has a width tells the browser to split the leftover horizontal space evenly between the left and right margins, which centres the box in its container.
Margins between stacked boxes can overlap. When one ordinary block sits on top of another, their vertical margins don't add up: a 20px bottom margin above a 30px top margin gives a 30px gap, not 50px. The larger one wins. This is called margin collapsing, and it only happens vertically, never left and right (and not between items inside a flexbox or grid layout).
You don't have to do the sums yourself. Right-click any element on any web page, choose Inspect, and the browser's developer tools open. In the styles area (Chrome calls the tab Computed; Firefox shows it under Layout) there's a diagram of nested rectangles, just like the one at the top of this page, labelled with the element's real content size, padding, border and margin. Hovering over it highlights each layer on the page in a different colour. When a layout looks wrong, that diagram is usually the fastest way to find the extra pixels.
Assume the default content-box unless the question says otherwise.
How wide is the visible box?
width: 300px; padding: 10px; border: 1px solid;
300 content + 10 + 10 padding + 1 + 1 border = 322px. Padding and border are added on both sides.
Same rule, but with box-sizing: border-box. How wide is the content area?
box-sizing: border-box;
width: 300px; padding: 10px; border: 1px solid;
The box is exactly 300px. Padding (20) and border (2) are taken out of it: 300 − 22 = 278px left for content.
How wide is the visible box (border included)?
width: 100px; margin: 20px;
Margin is transparent space outside the border. It isn't part of the box's size, though the box does need 140px of room in total.
How much padding is on the left side?
padding: 10px 20px;
With two values, the first is top and bottom, the second is left and right. So left and right each get 20px.
box-sizing: content-box), width is the content only. Visible width = width + left and right padding + left and right border.width: 50% columns wrap and width: 100% inputs overflow once you add padding.box-sizing: border-box makes width include padding and border. Most projects apply it to every element with *, *::before, *::after.width. Vertical margins between stacked blocks collapse to the larger one.Next time something is a few pixels too wide, don't nudge numbers until it fits. Add up the layers, or switch to border-box and let the width mean what it says.