A card is set to width: 100%, yet it spills out of its container. Another card uses box-sizing: border-box and still refuses to shrink inside a flex row. Two paragraphs each have a vertical margin, but the gap is smaller than the sum.
These are not three versions of the same bug. The first can come from how padding and borders contribute to width. The second often comes from an item's intrinsic minimum size. The third is normal margin-collapsing behavior.
The CSS box model is the right starting point for diagnosing all three, but it is not a complete layout algorithm. This guide separates the sizing model from the other rules that determine whether a box fits.
Start with the box you are actually measuring
A block box has four nested areas:
- Content: Text, images, and other content occupy this area.
- Padding: Space between the content and border. Backgrounds commonly extend into it.
- Border: The edge around the padding and content.
- Margin: Space outside the border, which influences surrounding layout but is not part of the border-box size.
When you inspect an element in the browser, its reported border-box dimensions are not necessarily equal to the width and height declarations. The distinction depends on box-sizing.
With box-sizing: content-box, an explicitly declared width sizes the content area. For a simple horizontal example:
.card {
box-sizing: content-box;
width: 240px;
padding: 20px;
border: 4px solid #315a82;
}
The border-box width is 240 + 20 + 20 + 4 + 4 = 288px. Left and right margins, if any, affect external spacing rather than the 288px border box.
Change only the sizing rule:
.card {
box-sizing: border-box;
width: 240px;
padding: 20px;
border: 4px solid #315a82;
}
Now the border box is 240px. The content area gets the space left after padding and borders: 240 - 40 - 8 = 192px.
Both widths were verified with a self-contained HTML fixture in headless Chromium 144. They describe this example's computed geometry, not a general guarantee that all content can fit inside a fixed-height or fixed-width box. See MDN's box model guide and box-sizing reference.
Failure 1: Why does width: 100% overflow its parent?
Suppose a parent has a definite content width of 320px:
<div class="wrapper">
<div class="panel">A panel that should fit</div>
</div>
.wrapper {
width: 320px;
}
.panel {
box-sizing: content-box;
width: 100%;
padding: 16px;
border: 2px solid #315a82;
}
The panel's content box takes 100% of the parent's content width (320px). Its padding adds 32px and its borders add 4px. Its final border-box width becomes 356px, wider than the 320px containing block.
The targeted fix is:
.panel {
box-sizing: border-box;
width: 100%;
padding: 16px;
border: 2px solid #315a82;
}
Under the same conditions, the panel now measures 320px from border to border. Both outcomes were checked in Chromium 144.
This does not mean every element with padding and no box-sizing rule overflows. A normal block with width: auto often sizes itself to the available space while accounting for its padding and border. The explicit width: 100% declaration is an important part of this example.
For a project-wide sizing convention, a commonly used reset includes pseudo-elements:
*,
*::before,
*::after {
box-sizing: border-box;
}
This is useful, but it does not disable minimum-content sizing, change how margins collapse, or automatically wrap a long unbroken string.
Failure 2: border-box is set, but a flex item still overflows
Imagine a row with a fixed label and a text region:
<div class="row">
<span class="label">Label</span>
<div class="copy">
supercalifragilisticexpialidocioussupercalifragilisticexpialidocious
</div>
</div>
.row {
display: flex;
width: 320px;
}
.label {
flex: 0 0 60px;
}
.copy {
box-sizing: border-box;
flex: 1 1 auto;
}
By default, flex items often have an automatic minimum size informed by their contents. With a long string lacking natural break opportunities, the text region can resist shrinking even when flex-shrink permits it. In the tested 320px row, its content caused the row's scroll width to reach 546px.
For text that is allowed to wrap, give the flexible region permission both to shrink and to break the token:
.copy {
box-sizing: border-box;
flex: 1 1 auto;
min-width: 0;
overflow-wrap: anywhere;
}
The same fixture then had a 320px scroll width. Both declarations have a distinct purpose:
min-width: 0removes the item's automatic minimum-width constraint.overflow-wrap: anywherelets an otherwise unbreakable word wrap before it spills beyond the shrunken item. The additional soft-wrap opportunities also affect the text'smin-contentwidth.
Do you need both? Not always. In this exact Chromium fixture, min-width: 0 alone allowed the item to become 260px wide, but the unbreakable text still overflowed and the row's scrollWidth remained 546px. overflow-wrap: anywhere alone reduced the row's scrollWidth to 320px, because the added wrapping opportunities also reduced the item's intrinsic minimum size. Using both produced the same 320px scroll width. This is why the two declarations solve related but different problems. It is not a universal rule that both are always required. See MDN's overflow-wrap explanation.
Do not blindly use overflow-wrap: anywhere for everything: a code identifier, URL, or product name might be better displayed with intentional wrapping or an explicitly scrollable area. Also note that some flex/grid scroll containers already have an automatic minimum of zero. See MDN's min-width documentation for those exceptions and its flex sizing reference.
If responsive card behavior depends on the width of a containing component rather than the viewport, that is a different question covered in the CSS container queries guide.
Failure 3: Why don't vertical margins add together?
Consider two adjacent block elements in normal document flow:
.first {
margin-bottom: 24px;
}
.second {
margin-top: 16px;
}
It is tempting to predict 40px of separation. In the normal block formatting context, adjacent vertical margins can collapse into a single margin. With these positive values, the resulting gap is 24px, not 40px. That result was also verified in the fixture.
Collapsing is not a rule that always chooses the largest margin regardless of sign: negative margins have different combination rules. Nor do all margins collapse. For example, flex and grid item margins do not collapse in the same way as adjoining block margins.
For a predictable repeated gap between stacked children, you can use a flex or grid container and gap:
.stack {
display: flex;
flex-direction: column;
gap: 24px;
}
.stack > * {
margin-block: 0;
}
Here the container controls the 24px gap. There are other ways to avoid a parent's margin collapsing with its child, including padding, borders, or establishing a new block formatting context, but each changes layout behavior and should be chosen intentionally.
MDN documents sibling, parent-child, empty-block, and negative-margin cases in its margin collapsing guide.
A repeatable DevTools investigation
When spacing is wrong, start with one specific element, not a global reset.
- Inspect the element using the browser's Elements panel.
- In the Box Model diagram, check which area has the unexpected size or spacing: content, padding, border, or margin.
- Look for
box-sizing,width,min-width,max-width,padding, andborderin its Styles and Computed panels. Check which declarations actually won the cascade. - If the element is a flex or grid item, inspect the parent's layout mode and the child's automatic minimum sizing before changing width values.
- If vertical spacing seems to disappear between blocks, inspect margin collapsing or whether a parent/child margin is escaping the expected boundary.
- Change one declaration at a time and observe the result at the problematic viewport width. Copy the corrected rule back into source code only after understanding what it affected.
Chrome's CSS inspection instructions describe the interactive Box Model diagram. Its CSS issue diagnosis guide explains the distinction between declared rules and the Computed pane.
A useful mental checklist:
| Symptom | First thing to check | What not to assume |
|---|---|---|
width: 100% element extends beyond parent | box-sizing plus horizontal padding/border | The browser always treats percentages as border-box widths |
| Flex item won't shrink | Automatic min-width, unbreakable content, wrapping | flex-shrink: 1 overrides every intrinsic constraint |
| Two vertical margins produce one gap | Margin collapsing in normal block flow | Margins always add together |
| Box dimensions look correct but text spills out | Content sizing and wrapping or overflow rules | border-box clips or wraps content |
| Gap is wrong in grid/flex | Parent gap, child margins, and alignment | Ordinary vertical margin collapse applies here |
The box model tells you what contributes to an element's dimensions. Normal flow, intrinsic sizing, Flexbox, and Grid determine how those boxes participate in a layout. Distinguishing those responsibilities is often the shortest route from a mysterious overflow bug to a specific CSS fix.
To understand how the browser reaches the layout and paint stages in the first place, continue with the browser rendering guide.
