What is the CSS box model, and what is the difference between content-box and border-box?
Advertisement
🧩 Scenario
Architecture Walkthrough
Four Layers, Inside Out
Every element the browser renders is a rectangular box composed of four concentric layers. The content box is innermost and holds the actual text, image, or child boxes. Wrapped around it is the padding box, transparent space that pushes content away from the edge. Around that sits the border box, a drawable frame with its own width, style, and colour. Outermost is the margin box, transparent space that separates this element from its neighbours.
The distinction that matters most in practice is where the background stops. Backgrounds and background images paint across the content and padding areas and, by default, extend under the border as well. They never paint into the margin. That is why margin is the right tool for spacing between elements and padding is the right tool for space inside a coloured or bordered element.
What the width Property Actually Sizes
Here is the part that surprises people: the width and height properties do not size the element. They size one specific layer of it, and which layer they size depends on box-sizing.
Under box-sizing: content-box, the CSS default, width sets the width of the content box only. Padding and border are then added on top. An element with width: 200px, padding: 20px, and a 5px border occupies 250px of horizontal space: 200 for content, 20 of padding on each side, and 5 of border on each side. Margin adds further space around that but is not part of the element box itself.
Under box-sizing: border-box, width sets the width of the border box, meaning it includes padding and border. That same declaration set produces an element exactly 200px wide on screen, with the content box shrinking to 150px to absorb the padding and border. The number you write is the number you get.
Why border-box Won
content-box is mathematically defensible but practically hostile. It means you cannot safely combine a percentage width with a pixel padding, because 25% + 32px overflows a four-column row. Developers worked around this for years with nested wrapper elements or calc(25% - 32px) gymnastics.
border-box removes the whole class of problem: percentages, padding, and borders compose without arithmetic. Because of that, essentially every modern reset, framework, and design system applies it globally. Tailwind's preflight does it, Bootstrap does it, and so does virtually every hand-rolled reset. Treat border-box as the practical default and content-box as legacy behaviour you should recognise but rarely choose.
Key Code Explained
/* content-box: width sizes the CONTENT only */
.content-box-card {
box-sizing: content-box; /* the CSS default */
width: 200px;
padding: 20px;
border: 5px solid #333;
/* rendered width = 200 + 20 + 20 + 5 + 5 = 250px */
}
/* border-box: width sizes CONTENT + PADDING + BORDER */
.border-box-card {
box-sizing: border-box;
width: 200px;
padding: 20px;
border: 5px solid #333;
/* rendered width = 200px exactly; content box shrinks to 150px */
}
/* The reset almost every project ships */
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Why it matters: this only works under border-box */
.column {
width: 25%;
padding: 16px;
/* content-box: 25% + 32px per column -> the fourth column wraps
border-box: four columns fit perfectly, padding eats inward */
}
/* Margin is outside the box: no background, and it does not
count toward the width under either box-sizing mode */
.spaced {
box-sizing: border-box;
width: 200px;
margin: 24px;
background: #eef; /* paints content + padding, never the margin */
}
The .column rule is the one worth memorising. It is the smallest possible demonstration of why the box model is not trivia: the exact same three declarations produce a working four-column row under one box-sizing value and a broken wrapping layout under the other. Nothing about the selector, the markup, or the parent changed.
The reset is worth reading closely too. It includes ::before and ::after because pseudo-elements are real boxes with their own box-sizing, and they do not inherit the value from their originating element the way you might expect from the * selector alone.
Tradeoffs
| Aspect | content-box | border-box |
|---|---|---|
What width sizes | Content only | Content + padding + border |
| Mixing % width with px padding | Overflows, needs calc() | Composes cleanly |
| Rendered size predictability | Must add layers mentally | Equals the declared value |
| Spec status | The CSS default | Opt-in via reset |
| When to prefer it | Rare: when content must be an exact size regardless of chrome | Effectively always |
What Interviewers Actually Check
- Whether you can name all four layers in order and say which ones are transparent
- Whether you can do the arithmetic for a rendered width under both
box-sizingmodes - Whether you understand that
widthsizes a layer, not the element - Whether you know margin sits outside the element and never receives the background
- Whether you can explain why
border-boxbecame the de facto standard rather than just reciting that it is
Follow-Up Questions
- Does
box-sizing: border-boxchange how margin participates in layout? Why or why not? - What happens under
border-boxif padding and border together exceed the declaredwidth? - How does
background-clipinteract with the box model layers, and what are its three main values? - Why do
widthandheighthave no effect on a non-replaced inline element like a<span>? - How do
min-widthandmax-widthinteract withbox-sizing, and are they measured against the same box?
Common Candidate Mistakes
- Assuming
width: 300pxguarantees a 300px footprint on screen, when undercontent-boxany padding or border silently widens it - Adding padding to a percentage-width column and then blaming flexbox or grid when the row wraps, instead of checking
box-sizing - Setting a background colour and expecting the margin area to be tinted, then adding a wrapper element to "fix" it rather than switching to padding
- Applying
box-sizing: border-boxto one problem element instead of resetting it globally, which leaves the rest of the codebase inconsistent - Conflating the box model, which describes an element's internal geometry, with the visual formatting model, which decides how those boxes flow, stack, and align relative to each other
Interview Readiness Checklist
Before you leave this question, make sure you can answer:
- Can you name the four layers of the box model from the inside out?
- Can you compute the on-screen width of an element given
width,padding, andborderunder bothbox-sizingmodes? - Can you explain exactly which property
border-boxredefines? - Can you explain why margin never shows the element background colour?
- Can you write the global
border-boxreset from memory, including the pseudo-element selectors?
Summary
The CSS box model describes every rendered element as four concentric layers: content, padding, border, and margin. Content and padding receive the background, the border is drawable, and the margin is transparent space outside the element that separates it from its neighbours. Understanding which layers are painted explains most of the day-to-day choice between padding and margin.
The width and height properties do not size the element as a whole; they size one layer, and box-sizing decides which. Under content-box, the CSS default, width sizes the content box and padding and border are added on top, so a 200px element with 20px padding and a 5px border renders 250px wide. Under border-box, width sizes the border box, so that same element renders exactly 200px wide and the content shrinks to absorb the chrome.
border-box is the practical default in modern CSS because it lets percentage widths, pixel padding, and borders coexist without calc() arithmetic. Nearly every reset and framework applies it globally to *, *::before, and *::after. Know content-box well enough to recognise its symptoms in legacy code, and reach for border-box everywhere else.
Which box-sizing value is the CSS default?
content-box is the spec default. Almost every modern codebase overrides it with a global border-box reset, which is why developers often forget content-box exists.
Does the box model apply to inline elements too?
Partly. Inline elements honour horizontal padding, border, and margin, but width, height, and vertical margins have no effect on them. Use inline-block or a flex/grid child if you need full box control.
Advertisement
Stay Updated
Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.
Advertisement