##### [The CSS Podcast - 001: The Box Model](https://thecsspodcast.libsyn.com/-the-css-podcast-box-model-episode-1)

Say you have this bit of HTML:

```html
<p>I am a paragraph of text that has a few words in it.</p>
```

Then you write this CSS for it:

```css
p {
  width: 100px;
  height: 50px;
  padding: 20px;
  border: 1px solid;
}
```

The content ends up 142px wide, instead of the 100px you specified, and it
breaks out of your element. Why is that?

The box model is a core foundation of CSS. Understanding how the box model
works, how it's affected by other aspects of CSS, and importantly,
how you can control it, can help you write more predictable CSS.
<iframe allow="camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;" loading="lazy" src="https://codepen.io/web-dot-dev/embed/WNRemxN?height=300&amp;theme-id=light&amp;default-tab=result&amp;editable=true" style="height: 100%; width: 100%; border: 0;"></iframe> Understanding the box model of CSS will help you figure out why your content doesn't fit inside an element.

It's important to remember that everything displayed by CSS is a box, even if
it's just some text, or has a `border-radius` that makes it look like a circle.

## Content and sizing

Boxes have different behavior based on their `display` value, their set
dimensions, and the content they contain. This content could be plain text, or
more boxes generated by child elements. Either way, the content affects the size
of the box by default.

You can control this using **extrinsic sizing** , or you can use **intrinsic sizing**
to let the browser make decisions for you based on the content size.

Here's a basic demo that explains the difference:
<iframe allow="camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;" loading="lazy" src="https://codepen.io/web-dot-dev/embed/abpoMBL?height=500&amp;theme-id=light&amp;default-tab=result&amp;editable=true" style="height: 100%; width: 100%; border: 0;"></iframe> When the box has extrinsic sizing, there's a limit to how much content you can add before it overflows out of the box. This makes the word "awesome" overflow.

The demo has the words "CSS is awesome" in a box with fixed dimensions and a
thick border. Because the box has a specified width, it's extrinsically sized.
This means it controls the sizing of its child content. However, the word
"awesome" is too large for the box, so it overflows outside the parent box's
**border box** (more on this later). One way to prevent this overflow is to let
the box be intrinsically sized by either not setting the width, or in this case,
setting the `width` to `min-content`. The `min-content` keyword tells the box to
be only as wide as the intrinsic minimum width of its content (the word
"awesome"). This lets the box fit perfectly around the text.

Here's a more complex example that shows the impact of different sizing on real
content:
<iframe allow="camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;" loading="lazy" src="https://codepen.io/web-dot-dev/embed/wvgwOJV?height=650&amp;theme-id=light&amp;default-tab=result&amp;editable=true" style="height: 100%; width: 100%; border: 0;"></iframe> Extrinsic sizing lets you control the size of an element. Intrinsic sizing prevents text overflow.

Toggle intrinsic sizing on and off to see how extrinsic sizing gives you more
control with extrinsic sizing and intrinsic sizing gives the content more
control. To see the effects add a few sentences of text to the card.
When this element has extrinsic sizing, there's a limit to how much content you
can add before it overflows, but that doesn't happen when intrinsic sizing is
toggled on.

By default, this element has a set `width` and `height` of `400px` each.
These dimensions give strict bounds to everything inside the element, which are
honored unless the content is too large for the box. You can see this in action
by changing the caption under the flower picture to something that exceeds the
height of the box.

Key term: Overflow happens when content is too big for the box it's in. You can
manage how an element handles overflow content using the `overflow` property.

Switching to intrinsic sizing lets the browser make decisions for you based on
the box's content size. This makes overflow much less likely because the box
resizes with its content.

It's important to remember that intrinsic sizing is the browser's default
behavior, and it usually provides much more flexibility than extrinsic sizing.

## The areas of the box model

Boxes are made up of distinct box model areas that all do a specific job.
![Diagram of the four main areas of the box model.](https://web.dev/static/learn/css/box-model/image/a-diagram-showing-four-m-af72960a9e79a.svg) The four main areas of the box model: content box, padding box, border box and margin box.

The **content box** is the area that the content lives in. The content can
control the size of its parent, so this is usually the most variably sized area.

The **padding box** surrounds the content box and is the space created by
the [`padding`](https://developer.mozilla.org/docs/Web/CSS/padding) property.
Because padding is inside the box, the box's background is visible in the space
it creates.
If the box has overflow rules set, such as `overflow: auto` or
`overflow: scroll`, the scrollbars also occupy this space.
<iframe allow="camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;" loading="lazy" src="https://codepen.io/web-dot-dev/embed/BaReoEV?height=500&amp;theme-id=light&amp;default-tab=result&amp;editable=true" style="height: 100%; width: 100%; border: 0;"></iframe> Scroll bars live in the padding box.

The **border box** surrounds the padding box, and its space is defined by the
[`border`](https://developer.mozilla.org/docs/Web/CSS/border) value, which
creates a visual frame for the element. The element's **border edge** is the
limit of what you can see.

The final area, the **margin box** , is the space around your box, defined by the
box's `margin` rule. Properties such as
[`outline`](https://developer.mozilla.org/docs/Web/CSS/outline) and
[`box-shadow`](https://developer.mozilla.org/docs/Web/CSS/box-shadow)
occupy this space too because they're painted on top of the element and don't
affect the size of the box. Changing your box's `outline-width` of `200px` on
a box doesn't change anything inside the border edge.
<iframe allow="camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;" loading="lazy" src="https://codepen.io/web-dot-dev/embed/XWprGea?height=500&amp;theme-id=light&amp;default-tab=result&amp;editable=true" style="height: 100%; width: 100%; border: 0;"></iframe> A wide outline doesn't affect the size of the rest of the element.

## A useful analogy

The box model is complex to understand, so here's an analogy for what you've
learned so far.

![Illustrating the box model with a picture frame.](https://web.dev/static/learn/css/box-model/image/three-photo-frames-610a106217f8d.jpg)

In this diagram, you have three picture frames mounted next to each other on a
wall. Elements of the framed image correspond to the box model as follows:

- The content box is the artwork.
- The padding box is the white mounting board, between the frame and the artwork.
- The border box is the frame, providing a literal border for the artwork.
- The margin box is the space between frames.
- The shadow occupies the same space as the margin box.

## Debug the box model

Browser developer tools provide a visualisation of a selected box's box model
calculations, which can help you understand how the box model works and how it
affects the website you're working on.

To try this in Chrome:

1. [Open DevTools](https://developer.chrome.com/docs/devtools/open).
2. [Select an element](https://developer.chrome.com/docs/devtools/css/reference#select).
3. Show the box model debugger.

The box model debugger for the soutline demo.

## Control the box model

To understand how to control the box model, you first need to understand what
happens in your browser.

Every browser applies a user agent style sheet to HTML documents. The style
sheet defines how elements should look and behave, if the elements aren't
given defined CSS. The CSS in user agent style sheets varies by browser, but
every browser has defaults that make content easier to read.

The user agent style sheet sets the default value for elements that take
`display`. For example, a `<div>` element's default `display` value is
`block`, a `<li>` has a default `display` value of `list-item`, and a `<span>`
has a default `display` value of `inline`.

An `inline` element has a block margin, but other elements don't respect it.
With `inline-block`, other elements respect the block margin, but the first
element keeps most of the same behaviors it had as an `inline` element.
A `block` item fills the available **inline space** by default, whereas
`inline` and `inline-block` elements are only as large as their content.

The user agent style sheet also sets defaults for `box-sizing`, which tells a
box how to calculate its size. By default, all elements are set to
`box-sizing: content-box;`. This means that when you set dimensions such
as `width` and `height`, those dimensions apply to the **content box** . If you
then set `padding` and `border`, these values are added to the content box
size.

### Check your understanding

Test your knowledge of box model size impacting properties.

```css
.my-box {
  width: 200px;
  border: 10px solid;
  padding: 20px;
}
```

How wide do you think `.my-box` will be?
200px Because the default value for box-sizing is content-box, padding and borders are added to the width. `200px` would be correct if the box had `box-sizing: border-box`. 260px The default box sizing is content-box, which means padding and borders are added to the overall box.

The actual width of this box is 260px.
Because the CSS uses the default `box-sizing: content-box`, the applied width is
the width of the content, and `padding` and `border` on both sides are added to
that. 200px for the content + 40px of padding + 20px of border makes a total
visible width of 260px.

You can change this by specifying `border-box` sizing:

    .my-box {
      box-sizing: border-box;
        width: 200px;
        border: 10px solid;
        padding: 20px;
    }

This alternative box model tells CSS to apply the `width` to the border box
instead of the content box. This means our `border` and `padding` get
*pushed in* , so when you set `.my-box` to be `200px` wide, it actually renders
at `200px` wide.

Check out how this works in the following interactive demo. When you toggle the
`box-sizing` value, the blue area shows which CSS is being applied *inside* the
box.
<iframe allow="camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi;" loading="lazy" src="https://codepen.io/web-dot-dev/embed/oNBvVpM?height=650&amp;theme-id=light&amp;default-tab=result&amp;editable=true" style="height: 100%; width: 100%; border: 0;"></iframe> Compare the effects of content-box and border-box sizing.

```css
*,
*::before,
*::after {
  box-sizing: border-box;
}
```

This CSS rule selects every element in the document and every `::before` and
`::after` pseudo element and applies `box-sizing: border-box`.
This means that every element now uses this alternative box model.

Because the alternative box model can be more predictable, developers often add
this rule to resets and normalizers, such as
[A (more) Modern CSS Reset](https://piccalil.li/blog/a-modern-css-reset).

## Resources

- [Introduction to the box model](https://developer.mozilla.org/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model)
- [What are browser developer tools?](https://developer.mozilla.org/docs/Learn/Common_questions/What_are_browser_developer_tools)

### User agent stylesheets

- [Chromium](https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css)
- [Firefox](https://searchfox.org/mozilla-central/source/layout/style/res/html.css)
- [Webkit](https://github.com/WebKit/WebKit/blob/main/Source/WebCore/css/html.css)