Skip to main content
Technical Systems

CSS Box Model: How Browsers Calculate Size and Spacing

CSS layout begins with content, padding, border, and margin.

A practical guide to the CSS box model, including content-box, border-box, padding, borders, margins, margin collapse, overflow, and layout debugging.

CSS Box Model: How Browsers Calculate Size and Spacing

A web page may look like text, buttons, images, cards, forms, and navigation, but CSS has a simpler way of looking at it. Every HTML element generates one or more boxes, and the browser has to determine how large those boxes are and how much space they occupy.

That is the CSS box model.

If you give a <div> a width of 300px, add 20px of padding, and then add a border, you might reasonably expect the element to remain 300 pixels wide. Under the default box model, it does not. The declared width describes only part of the box.

Understanding why makes many seemingly strange CSS layout problems much easier to diagnose.

An HTML Element Is More Than Its Content

Start with a simple element:

<div class="card">
  Hello
</div>

Without much styling, it is easy to think of the card as nothing more than the space occupied by Hello. CSS instead builds several layers around that content.

+---------------------------+
|          margin           |
|   +-------------------+   |
|   |      border       |   |
|   |   +-----------+   |   |
|   |   |  padding  |   |   |
|   |   | +-------+ |   |   |
|   |   | |content| |   |   |
|   |   | +-------+ |   |   |
|   |   +-----------+   |   |
|   +-------------------+   |
+---------------------------+

The content box is where text, images, or other child content appears. Padding creates space between that content and the border, while the border surrounds the padded content.

Margin sits outside the border. It creates separation between the element and surrounding boxes rather than enlarging the element’s visible background.

Those four areas content, padding, border, and margin are the basic box model.

Width Does Not Always Mean the Width You See

Suppose a card has these styles:

.card {
  width: 300px;
  padding: 20px;
  border: 2px solid black;
}

By default, browsers use box-sizing: content-box. That means width: 300px sets the width of the content box.

The padding and borders are then added around it.

300px content
+ 40px horizontal padding
+  4px horizontal border
----------------------------
344px visible width

If the card also has margin: 10px, another 20 pixels of horizontal space surrounds it. Its visible border box is still 344 pixels wide, but the space involved in laying it out alongside neighboring elements can now reach 364 pixels.

Height works according to the same basic model. A declared height can describe the content area while vertical padding and borders add to the rendered box.

This is one reason an element can overflow a container even though its CSS appears to say width: 100%.

.child {
  width: 100%;
  padding: 20px;
}

With content-box, the content itself consumes 100% of the available width, and the padding is added afterward.

Border-Box Changes What Width Means

A common way to make sizing easier is:

* {
  box-sizing: border-box;
}

With border-box, the declared width includes the content, padding, and border.

The same card can now be written as:

.card {
  box-sizing: border-box;
  width: 300px;
  padding: 20px;
  border: 2px solid black;
}

Its total border-box width remains 300 pixels. The browser takes the padding and border out of the space available for the content.

300px total width
├── 2px border
├── 20px padding
├── remaining content width
├── 20px padding
└── 2px border

Margin remains outside that calculation.

Neither sizing model is inherently incorrect. content-box means “make the content this wide,” while border-box means “make the bordered element this wide.”

For application layouts, border-box is often easier to reason about because adding padding does not unexpectedly increase a declared width, which matters when frontend components need repeatable behavior in tests.

Not Every Box Behaves Like a Block

The box model applies broadly, but not every HTML element participates in layout in exactly the same way.

A typical block element such as a <div> begins on a new line and usually expands across the available inline space. Width, height, padding, borders, and margins fit naturally into the rectangular model developers often have in mind.

Inline content behaves differently because it flows inside lines of text.

Consider:

<p>
  Read the <span class="highlight">important section</span> first.
</p>

The <span> generates an inline box that participates in the surrounding text flow. Horizontal padding and margins can affect that flow, but explicit width and height do not behave as they do on a normal block box.

An inline element can even be split across multiple line boxes when its text wraps.

That is why debugging a box-model problem sometimes requires asking more than “what are its width and padding?” You also need to know what kind of box is participating in layout, especially when text, images, and SVG or PNG assets behave differently inside the same interface.

inline-block, flex items, and grid items introduce further behavior, but they still build on the same underlying ideas about content, padding, borders, and surrounding space.

Margins Have One Particularly Surprising Behavior

Padding is usually straightforward: if an element has 20 pixels of top padding, there are 20 pixels between its content and its top border.

Vertical margins between ordinary block elements can behave differently because they may collapse.

Suppose two paragraphs are stacked:

.first {
  margin-bottom: 30px;
}

.second {
  margin-top: 20px;
}

You might expect 50 pixels between them. In a normal block formatting context, those adjoining vertical margins can collapse, producing 30 pixels instead.

first paragraph

  30px gap

second paragraph

The margins are not simply being added together.

Margin collapsing also explains some confusing parent-and-child spacing behavior. Under the right conditions, a child’s top or bottom margin can collapse with its parent’s margin rather than creating the internal separation a developer expected.

Padding does not collapse. If the desired space is clearly supposed to exist inside a container, padding is often the more accurate tool.

Overflow Reveals When the Box No Longer Fits

Once the browser has calculated a box, its content still has to fit inside it.

Consider a fixed-height container:

.panel {
  height: 100px;
}

If its content requires more vertical space than that, the content can overflow the box. The overflow property determines what should happen.

.panel {
  height: 100px;
  overflow: auto;
}

Depending on the chosen value, overflowing content may remain visible, be clipped, or become scrollable.

Overflow problems are often really sizing problems in disguise. A fixed width may not include padding the way you expected, a child may have a minimum size that prevents shrinking, or content may simply require more room than the box was given, the same kind of mismatch that makes visual regression checks useful in frontend work.

The useful question is therefore not just “why is this overflowing?” It is “what size did the browser actually calculate for this box, and what is forcing its contents beyond that size?”

Layout Is a Conversation Between Boxes

The box model becomes most useful when you stop thinking about individual CSS properties in isolation.

A card with:

.card {
  width: 400px;
  padding: 24px;
  margin-bottom: 16px;
}

contains several different spacing decisions. The width controls sizing according to the selected box-sizing model, padding creates breathing room inside the card, and margin separates the card from neighboring layout boxes.

Those are different jobs.

A common source of messy CSS is using whichever spacing property seems to move something into the right place. That may fix the immediate visual problem while making the layout difficult to reason about later.

Thinking in boxes gives the spacing a purpose:

content ← padding → border ← margin → neighboring box

Padding belongs to the element’s interior. Margin describes separation outside it.

Modern flexbox and grid layouts add another useful spacing mechanism: gap. When the intention is simply to create consistent space between children in a flex or grid container, gap can often express that relationship more directly than assigning margins to individual children.

The Browser Has Already Done the Math for You

You do not have to calculate every box by hand.

Browser DevTools can show the computed box model for an element, usually as a diagram containing its content dimensions, padding, border, and margin. Inspecting an element often reveals immediately that a supposedly 300-pixel box is wider because padding has been added, or that unexpected space comes from a margin rather than the parent.

That makes the box-model view one of the most useful places to start when debugging CSS.

If an element is too wide, check its computed width, padding, borders, and box-sizing. If two elements are farther apart than expected, inspect their margins and any container gap. If spacing seems to disappear, consider margin collapsing. If content escapes its container, inspect the computed dimensions and overflow behavior.

The important shift is from adjusting CSS until the page happens to look right to asking what box the browser actually constructed.

Once that box is visible, many layout bugs stop being mysterious. The CSS box model is the browser’s accounting system for space: content needs room, padding surrounds it, borders enclose it, margins separate it, and box-sizing determines which of those layers a declared width or height is actually measuring.