Prose - Component
Simple rules to help longform content—prose—read as niceley as it can.
Code
Source (Nunjucks)
<div class="prose">
<p>Say you have this bit of HTML:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>I am a paragraph of text that has a few words in it.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span></code></pre>
<p>Then you write this CSS for it:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">p</span> <span class="token punctuation">{</span><br> <span class="token property">width</span><span class="token punctuation">:</span> 100px<span class="token punctuation">;</span><br> <span class="token property">height</span><span class="token punctuation">:</span> 50px<span class="token punctuation">;</span><br> <span class="token property">padding</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span><br> <span class="token property">border</span><span class="token punctuation">:</span> 1px solid<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>The content would break out of your element and it would be 142px wide, rather than 100px. Why is that? The box model is a core foundation of CSS and understanding how it works, how it is affected by other aspects of CSS and importantly, how you can control it will help you to write more predictable CSS.</p>
<figure>
<div style="height: 300px; width: 100%">
<iframe src="https://codepen.io/web-dot-dev/embed/WNRemxN?height=300&theme-id=light&default-tab=result&editable=true" style="height: 100%; width: 100%; border: 0;" title="Pen WNRemxN by web-dot-dev on Codepen"></iframe>
</div>
</figure>
<p>A really important thing to remember when writing CSS, or working on the web as a whole, is that everything displayed by CSS is a box. Whether that's a box that uses <code>border-radius</code> to look like a circle, or even just some text: the key thing to remember is that it's all boxes.</p>
<h2 id="content-and-sizing">Content and sizing <a class="headline-link" href="#content-and-sizing">#</a></h2>
<p>Boxes have different behavior based on their <code>display</code> value, their set dimensions, and the content that lives within them. This content could be even more boxes—generated by child elements—or plain text content. Either way, this content will affect the size of the box by default.</p>
<p>You can control this by using <strong>extrinsic sizing</strong>, or, you can continue to let the browser make decisions for you based on the content size, using <strong>intrinsic sizing</strong>.</p>
<p>Let's quickly look at the difference, using a demo to help us.</p>
<figure>
<div style="height: 500px; width: 100%">
<iframe src="https://codepen.io/web-dot-dev/embed/abpoMBL?height=500&theme-id=light&default-tab=result&editable=true" style="height: 100%; width: 100%; border: 0;" title="Pen abpoMBL by web-dot-dev on Codepen"></iframe>
</div>
<figcaption>
Notice that when the box is using extrinsic sizing, there's a limit of how much content you can add before it overflows out of the box's bounds. This makes the word, "awesome", overflow.
</figcaption>
</figure>
<p>The demo has the words, "CSS is awesome" in a box with fixed dimensions and a thick border. The box has a width, so is extrinsically sized. It controls the sizing of its child content. The problem with this though, is that the word "awesome" is too large for the box, so it overflows outside of the parent box's <strong>border box</strong> (more on this later in the lesson). One way to prevent this overflow is to allow the box to be intrinsically sized by either unsetting the width, or in this case, setting the <code>width</code> to be <code>min-content</code>. The <code>min-content</code> keyword tells the box to only be as wide as the intrinsic minimum width of its content (the word "awesome"). This allows the box to fit around "CSS is awesome", perfectly.</p>
<p>Let's look at something more complex to see the impact of different sizing on real content:</p>
<figure>
<div style="height: 650px; width: 100%">
<iframe src="https://codepen.io/web-dot-dev/embed/wvgwOJV?height=650&theme-id=light&default-tab=result&editable=true" style="height: 100%; width: 100%; border: 0;" title="Pen wvgwOJV by web-dot-dev on Codepen"></iframe>
</div>
</figure>
<p>Toggle intrinsic sizing on and off to see how you can gain more control with extrinsic sizing and let the content have more control with intrinsic sizing. To see the effect that intrinsic and extrinsic sizing has, add a few sentences of content to the card. When this element is using extrinsic sizing, there's a limit of how much content you can add before it overflows out of the element's bounds, but this isn't the case when intrinsic sizing is toggled on.</p>
<p>By default, this element has a set <code>width</code> and <code>height</code>—both <code>400px</code>. These dimensions give strict bounds to everything inside the element, which will be honored unless the content is too large for the box in which case visible overflow will happen. You can see this in action by changing the content of the caption, under the flower picture to something that exceeds the height of the box, which is a few lines of content.</p>
<div class="aside flow color-secondary-box-text bg-secondary-box-bg">
<p><strong>Key Term</strong>: When content is too big for the box it is in, we call this overflow. You can manage how an element handles overflow content, using the <code>overflow</code> property.</p>
</div>
<p>When you switch to intrinsic sizing, you are letting the browser make decisions for you, based on the box's content size. It's much more difficult for there to be overflow with intrinsic sizing because our box will resize with its content, rather than try to size the content. It's important to remember that this is the default, flexible behavior of a browser. Though extrinsic sizing gives more control on the surface, intrinsic sizing provides the most flexibility, most of the time.</p>
<h2 id="the-areas-of-the-box-model">The areas of the box model <a class="headline-link" href="#the-areas-of-the-box-model">#</a></h2>
<p>Boxes are made up of distinct box model areas that all do a specific job.</p>
<figure>
<img alt="A diagram showing the four main areas of the box model - content box, padding box, border box and margin box" height="547" src="https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/ECuEOJEGnudhXW5JEFih.svg" width="800">
<figcaption>
The four main areas of the box model: content box, padding box, border box and margin box.
</figcaption>
</figure>
<p>You start with <strong>content box</strong>, which is the area that the content lives in. As you learned before: this content can control the size of its parent, so is usually the most variably sized area.</p>
<p>The <strong>padding box</strong> surrounds the content box and is the space created by the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/padding" rel="noopener"><code>padding</code></a> property. Because padding is inside the box, the background of the box will be visible in the space that it creates. If our box has overflow rules set, such as <code>overflow: auto</code> or <code>overflow: scroll</code>, the scrollbars will occupy this space too.</p>
<figure>
<div style="height: 500px; width: 100%">
<iframe src="https://codepen.io/web-dot-dev/embed/BaReoEV?height=500&theme-id=light&default-tab=result&editable=true" style="height: 100%; width: 100%; border: 0;" title="Pen BaReoEV by web-dot-dev on Codepen"></iframe>
</div>
</figure>
<p>The <strong>border box</strong> surrounds the padding box and its space is occupied by the <code>border</code> value. The border box is the bounds of your box and the <strong>border edge</strong> is the limit of what you can visually see. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/border" rel="noopener"><code>border</code></a> property is used to visually frame an element.</p>
<p>The final area, the <strong>margin box</strong>, is the space around your box, defined by the <code>margin</code> rule on your box. Properties such as <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/outline" rel="noopener"><code>outline</code></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow" rel="noopener"><code>box-shadow</code></a> occupy this space too because they are painted on top, so they don't affect the size of our box. You could have an <code>outline-width</code> of <code>200px</code> on our box and everything inside and including the border box would be exactly the same size.</p>
<figure>
<div style="height: 500px; width: 100%">
<iframe src="https://codepen.io/web-dot-dev/embed/XWprGea?height=500&theme-id=light&default-tab=result&editable=true" style="height: 100%; width: 100%; border: 0;" title="Pen XWprGea by web-dot-dev on Codepen"></iframe>
</div>
</figure>
<h2 id="a-useful-analogy">A useful analogy <a class="headline-link" href="#a-useful-analogy">#</a></h2>
<p>The box model is complex to understand, so let's recap what you've learned with an analogy.</p>
<figure>
<img alt="Three photo frames" height="562" sizes="(min-width: 800px) 800px, calc(100vw - 48px)" src="https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format" srcset="https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=200 200w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=228 228w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=260 260w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=296 296w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=338 338w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=385 385w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=439 439w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=500 500w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=571 571w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=650 650w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=741 741w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=845 845w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=964 964w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1098 1098w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1252 1252w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1428 1428w, https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1600 1600w" width="800">
</figure>
<p>In this diagram, you have three photo frames, mounted to a wall, next to each other. The diagram has labels that associate elements of the frame with the box model.</p>
<p>To break this analogy down:</p>
<ul>
<li>The content box is the artwork.</li>
<li>The padding box is the white matte, between the frame and the artwork.</li>
<li>The border box is the frame, providing a literal border for the artwork.</li>
<li>The margin box is the space between each frame.</li>
<li>The shadow occupies the same space as the margin box.</li>
</ul>
<h2 id="debugging-the-box-model">Debugging the box model <a class="headline-link" href="#debugging-the-box-model">#</a></h2>
<p>Browser DevTools provide a visualisation of a selected box's box model calculations, which can help you understand how the box model works and importantly, how it is affecting the website you're working on.</p>
<p>Go ahead and try this in your own browser:</p>
<ol>
<li>
<a href="https://developers.google.com/web/tools/chrome-devtools/open" rel="noopener">Open DevTools</a>
</li>
<li>
<a href="https://developers.google.com/web/tools/chrome-devtools/css/reference#select" rel="noopener">Select an element</a>
</li>
<li>Show the box model debugger</li>
</ol>
<figure>
<video controls=""><source src="https://storage.googleapis.com/web-dev-uploads/video/VbAJIREinuYvovrBzzvEyZOpw5w1/sKdHrAfqahgWfDVQEBBT.mp4" type="video/mp4"></video>
</figure>
<h2 id="controlling-the-box-model">Controlling the box model <a class="headline-link" href="#controlling-the-box-model">#</a></h2>
<p>To understand how to control the box model, you first need to understand what happens in your browser.</p>
<p>Every browser applies a user agent stylesheet to HTML documents. The CSS used varies between each browser, but they provide sensible defaults to make content easier to read. They define how elements should look and behave if there's no CSS defined. It is in the user agent styles where a box's default <code>display</code> is set, too. For example, if we are in a normal flow, a <code><div></code> element's default <code>display</code> value is <code>block</code>, a <code><li></code> has a default <code>display</code> value of <code>list-item</code>, and a <code><span></code> has a default <code>display</code> value of <code>inline</code>.</p>
<p>An <code>inline</code> element has block margin, but other elements won't respect it. Use <code>inline-block</code>, and those elements will respect the block margin, while the element maintains most of the same behaviors it had as an <code>inline</code> element. A <code>block</code> item will, by default, fill the available <strong>inline space</strong>, whereas a <code>inline</code> and <code>inline-block</code> elements will only be as large as their content.</p>
<p>Alongside an understanding of how user agent styles affect each box, you also need to understand <code>box-sizing</code>, which tells our box how to calculate its box size. By default, all elements have the following user agent style: <code>box-sizing: content-box;</code>.</p>
<p>Having <code>content-box</code> as the value of <code>box-sizing</code> means that when you set dimensions, such as a <code>width</code> and <code>height</code>, they will be applied to the <strong>content box</strong>. If you then set <code>padding</code> and <code>border</code>, these values will be added to the content box's size.</p>
<p>The actual width of this box will be 260px. As the CSS uses the default <code>box-sizing: content-box</code>, the applied width is the width of the content, <code>padding</code> and <code>border</code> on both sides are added to that. So 200px for the content + 40px of padding + 20px of border makes a total visible width of 260px.</p>
<p>You <em>can</em> control this, though, by making the following modification to use the alternative box model, <code>border-box</code>:</p>
<pre class="language-css"><code class="language-css"><span class="highlight-line"><span class="token selector">.my-box</span> <span class="token punctuation">{</span></span><br><mark class="highlight-line highlight-line-active"> <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span></mark><br><span class="highlight-line"> <span class="token property">width</span><span class="token punctuation">:</span> 200px<span class="token punctuation">;</span></span><br><span class="highlight-line"> <span class="token property">border</span><span class="token punctuation">:</span> 10px solid<span class="token punctuation">;</span></span><br><span class="highlight-line"> <span class="token property">padding</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>This alternative box model tells CSS to apply the <code>width</code> to the border box instead of the content box. This means that our <code>border</code> and <code>padding</code> get <em>pushed in</em>, and as a result, when you set <code>.my-box</code> to be <code>200px</code> wide: it actually renders at <code>200px</code> wide.</p>
<p>Check out how this works in the following interactive demo. Notice that when you toggle the <code>box-sizing</code> value it shows—via a blue background—which CSS is being applied <em>inside</em> our box.</p>
<figure>
<div style="height: 650px; width: 100%">
<iframe src="https://codepen.io/web-dot-dev/embed/oNBvVpM?height=650&theme-id=light&default-tab=result&editable=true" style="height: 100%; width: 100%; border: 0;" title="Pen oNBvVpM by web-dot-dev on Codepen"></iframe>
</div>
</figure>
<pre class="language-css"><code class="language-css"><span class="token selector">*,<br>*::before,<br>*::after</span> <span class="token punctuation">{</span><br> <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>This CSS rule selects every element in the document and every <code>::before</code> and <code>::after</code> pseudo element and applies <code>box-sizing: border-box</code>. This means that every element will now have this alternative box model.</p>
<p>Because the alternative box model can be more predictable, developers often add this rule to resets and normalizers, <a href="https://piccalil.li/blog/a-modern-css-reset" rel="noopener">like this one</a>.</p>
<h2 id="resources">Resources <a class="headline-link" href="#resources">#</a></h2>
<ul>
<li>
<a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model" rel="noopener">Introduction to the box model</a>
</li>
<li>
<a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools" rel="noopener">What are browser developer tools?</a>
</li>
</ul>
<h3 id="user-agent-stylesheets">User agent stylesheets <a class="headline-link" href="#user-agent-stylesheets">#</a></h3>
<ul>
<li>
<a href="https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css" rel="noopener">Chromium</a>
</li>
<li>
<a href="https://searchfox.org/mozilla-central/source/layout/style/res/html.css" rel="noopener">Firefox</a>
</li>
<li>
<a href="https://trac.webkit.org/browser/trunk/Source/WebCore/css/html.css" rel="noopener">Webkit</a>
</li>
</ul>
</div>
Output
<div class="prose">
<p>Say you have this bit of HTML:</p>
<pre
class="language-html"
><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>I am a paragraph of text that has a few words in it.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span></code></pre>
<p>Then you write this CSS for it:</p>
<pre
class="language-css"
><code class="language-css"><span class="token selector">p</span> <span class="token punctuation">{</span><br> <span class="token property">width</span><span class="token punctuation">:</span> 100px<span class="token punctuation">;</span><br> <span class="token property">height</span><span class="token punctuation">:</span> 50px<span class="token punctuation">;</span><br> <span class="token property">padding</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span><br> <span class="token property">border</span><span class="token punctuation">:</span> 1px solid<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>
The content would break out of your element and it would be 142px wide,
rather than 100px. Why is that? The box model is a core foundation of CSS
and understanding how it works, how it is affected by other aspects of CSS
and importantly, how you can control it will help you to write more
predictable CSS.
</p>
<figure>
<div style="height: 300px; width: 100%">
<iframe
src="https://codepen.io/web-dot-dev/embed/WNRemxN?height=300&theme-id=light&default-tab=result&editable=true"
style="height: 100%; width: 100%; border: 0"
title="Pen WNRemxN by web-dot-dev on Codepen"
></iframe>
</div>
</figure>
<p>
A really important thing to remember when writing CSS, or working on the web
as a whole, is that everything displayed by CSS is a box. Whether that's a
box that uses <code>border-radius</code> to look like a circle, or even just
some text: the key thing to remember is that it's all boxes.
</p>
<h2 id="content-and-sizing">
Content and sizing <a class="headline-link" href="#content-and-sizing">#</a>
</h2>
<p>
Boxes have different behavior based on their <code>display</code> value,
their set dimensions, and the content that lives within them. This content
could be even more boxes—generated by child elements—or plain text content.
Either way, this content will affect the size of the box by default.
</p>
<p>
You can control this by using <strong>extrinsic sizing</strong>, or, you can
continue to let the browser make decisions for you based on the content
size, using <strong>intrinsic sizing</strong>.
</p>
<p>Let's quickly look at the difference, using a demo to help us.</p>
<figure>
<div style="height: 500px; width: 100%">
<iframe
src="https://codepen.io/web-dot-dev/embed/abpoMBL?height=500&theme-id=light&default-tab=result&editable=true"
style="height: 100%; width: 100%; border: 0"
title="Pen abpoMBL by web-dot-dev on Codepen"
></iframe>
</div>
<figcaption>
Notice that when the box is using extrinsic sizing, there's a limit of how
much content you can add before it overflows out of the box's bounds. This
makes the word, "awesome", overflow.
</figcaption>
</figure>
<p>
The demo has the words, "CSS is awesome" in a box with fixed dimensions and
a thick border. The box has a width, so is extrinsically sized. It controls
the sizing of its child content. The problem with this though, is that the
word "awesome" is too large for the box, so it overflows outside of the
parent box's <strong>border box</strong> (more on this later in the lesson).
One way to prevent this overflow is to allow the box to be intrinsically
sized by either unsetting the width, or in this case, setting the
<code>width</code> to be <code>min-content</code>. The
<code>min-content</code> keyword tells the box to only be as wide as the
intrinsic minimum width of its content (the word "awesome"). This allows the
box to fit around "CSS is awesome", perfectly.
</p>
<p>
Let's look at something more complex to see the impact of different sizing
on real content:
</p>
<figure>
<div style="height: 650px; width: 100%">
<iframe
src="https://codepen.io/web-dot-dev/embed/wvgwOJV?height=650&theme-id=light&default-tab=result&editable=true"
style="height: 100%; width: 100%; border: 0"
title="Pen wvgwOJV by web-dot-dev on Codepen"
></iframe>
</div>
</figure>
<p>
Toggle intrinsic sizing on and off to see how you can gain more control with
extrinsic sizing and let the content have more control with intrinsic
sizing. To see the effect that intrinsic and extrinsic sizing has, add a few
sentences of content to the card. When this element is using extrinsic
sizing, there's a limit of how much content you can add before it overflows
out of the element's bounds, but this isn't the case when intrinsic sizing
is toggled on.
</p>
<p>
By default, this element has a set <code>width</code> and
<code>height</code>—both <code>400px</code>. These dimensions give strict
bounds to everything inside the element, which will be honored unless the
content is too large for the box in which case visible overflow will happen.
You can see this in action by changing the content of the caption, under the
flower picture to something that exceeds the height of the box, which is a
few lines of content.
</p>
<div class="aside flow color-secondary-box-text bg-secondary-box-bg">
<p>
<strong>Key Term</strong>: When content is too big for the box it is in,
we call this overflow. You can manage how an element handles overflow
content, using the <code>overflow</code> property.
</p>
</div>
<p>
When you switch to intrinsic sizing, you are letting the browser make
decisions for you, based on the box's content size. It's much more difficult
for there to be overflow with intrinsic sizing because our box will resize
with its content, rather than try to size the content. It's important to
remember that this is the default, flexible behavior of a browser. Though
extrinsic sizing gives more control on the surface, intrinsic sizing
provides the most flexibility, most of the time.
</p>
<h2 id="the-areas-of-the-box-model">
The areas of the box model
<a class="headline-link" href="#the-areas-of-the-box-model">#</a>
</h2>
<p>
Boxes are made up of distinct box model areas that all do a specific job.
</p>
<figure>
<img
alt="A diagram showing the four main areas of the box model - content box, padding box, border box and margin box"
height="547"
src="https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/ECuEOJEGnudhXW5JEFih.svg"
width="800"
/>
<figcaption>
The four main areas of the box model: content box, padding box, border box
and margin box.
</figcaption>
</figure>
<p>
You start with <strong>content box</strong>, which is the area that the
content lives in. As you learned before: this content can control the size
of its parent, so is usually the most variably sized area.
</p>
<p>
The <strong>padding box</strong> surrounds the content box and is the space
created by the
<a
href="https://developer.mozilla.org/en-US/docs/Web/CSS/padding"
rel="noopener"
><code>padding</code></a
>
property. Because padding is inside the box, the background of the box will
be visible in the space that it creates. If our box has overflow rules set,
such as <code>overflow: auto</code> or <code>overflow: scroll</code>, the
scrollbars will occupy this space too.
</p>
<figure>
<div style="height: 500px; width: 100%">
<iframe
src="https://codepen.io/web-dot-dev/embed/BaReoEV?height=500&theme-id=light&default-tab=result&editable=true"
style="height: 100%; width: 100%; border: 0"
title="Pen BaReoEV by web-dot-dev on Codepen"
></iframe>
</div>
</figure>
<p>
The <strong>border box</strong> surrounds the padding box and its space is
occupied by the <code>border</code> value. The border box is the bounds of
your box and the <strong>border edge</strong> is the limit of what you can
visually see. The
<a
href="https://developer.mozilla.org/en-US/docs/Web/CSS/border"
rel="noopener"
><code>border</code></a
>
property is used to visually frame an element.
</p>
<p>
The final area, the <strong>margin box</strong>, is the space around your
box, defined by the <code>margin</code> rule on your box. Properties such as
<a
href="https://developer.mozilla.org/en-US/docs/Web/CSS/outline"
rel="noopener"
><code>outline</code></a
>
and
<a
href="https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow"
rel="noopener"
><code>box-shadow</code></a
>
occupy this space too because they are painted on top, so they don't affect
the size of our box. You could have an <code>outline-width</code> of
<code>200px</code> on our box and everything inside and including the border
box would be exactly the same size.
</p>
<figure>
<div style="height: 500px; width: 100%">
<iframe
src="https://codepen.io/web-dot-dev/embed/XWprGea?height=500&theme-id=light&default-tab=result&editable=true"
style="height: 100%; width: 100%; border: 0"
title="Pen XWprGea by web-dot-dev on Codepen"
></iframe>
</div>
</figure>
<h2 id="a-useful-analogy">
A useful analogy <a class="headline-link" href="#a-useful-analogy">#</a>
</h2>
<p>
The box model is complex to understand, so let's recap what you've learned
with an analogy.
</p>
<figure>
<img
alt="Three photo frames"
height="562"
sizes="(min-width: 800px) 800px, calc(100vw - 48px)"
src="https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format"
srcset="
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=200 200w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=228 228w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=260 260w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=296 296w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=338 338w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=385 385w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=439 439w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=500 500w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=571 571w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=650 650w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=741 741w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=845 845w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=964 964w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1098 1098w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1252 1252w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1428 1428w,
https://web-dev.imgix.net/image/VbAJIREinuYvovrBzzvEyZOpw5w1/FBaaJXdnuSkvOx1nB0CB.jpg?auto=format&w=1600 1600w
"
width="800"
/>
</figure>
<p>
In this diagram, you have three photo frames, mounted to a wall, next to
each other. The diagram has labels that associate elements of the frame with
the box model.
</p>
<p>To break this analogy down:</p>
<ul>
<li>The content box is the artwork.</li>
<li>
The padding box is the white matte, between the frame and the artwork.
</li>
<li>
The border box is the frame, providing a literal border for the artwork.
</li>
<li>The margin box is the space between each frame.</li>
<li>The shadow occupies the same space as the margin box.</li>
</ul>
<h2 id="debugging-the-box-model">
Debugging the box model
<a class="headline-link" href="#debugging-the-box-model">#</a>
</h2>
<p>
Browser DevTools provide a visualisation of a selected box's box model
calculations, which can help you understand how the box model works and
importantly, how it is affecting the website you're working on.
</p>
<p>Go ahead and try this in your own browser:</p>
<ol>
<li>
<a
href="https://developers.google.com/web/tools/chrome-devtools/open"
rel="noopener"
>Open DevTools</a
>
</li>
<li>
<a
href="https://developers.google.com/web/tools/chrome-devtools/css/reference#select"
rel="noopener"
>Select an element</a
>
</li>
<li>Show the box model debugger</li>
</ol>
<figure>
<video controls="">
<source
src="https://storage.googleapis.com/web-dev-uploads/video/VbAJIREinuYvovrBzzvEyZOpw5w1/sKdHrAfqahgWfDVQEBBT.mp4"
type="video/mp4"
/>
</video>
</figure>
<h2 id="controlling-the-box-model">
Controlling the box model
<a class="headline-link" href="#controlling-the-box-model">#</a>
</h2>
<p>
To understand how to control the box model, you first need to understand
what happens in your browser.
</p>
<p>
Every browser applies a user agent stylesheet to HTML documents. The CSS
used varies between each browser, but they provide sensible defaults to make
content easier to read. They define how elements should look and behave if
there's no CSS defined. It is in the user agent styles where a box's default
<code>display</code> is set, too. For example, if we are in a normal flow, a
<code><div></code> element's default <code>display</code> value is
<code>block</code>, a <code><li></code> has a default
<code>display</code> value of <code>list-item</code>, and a
<code><span></code> has a default <code>display</code> value of
<code>inline</code>.
</p>
<p>
An <code>inline</code> element has block margin, but other elements won't
respect it. Use <code>inline-block</code>, and those elements will respect
the block margin, while the element maintains most of the same behaviors it
had as an <code>inline</code> element. A <code>block</code> item will, by
default, fill the available <strong>inline space</strong>, whereas a
<code>inline</code> and <code>inline-block</code> elements will only be as
large as their content.
</p>
<p>
Alongside an understanding of how user agent styles affect each box, you
also need to understand <code>box-sizing</code>, which tells our box how to
calculate its box size. By default, all elements have the following user
agent style: <code>box-sizing: content-box;</code>.
</p>
<p>
Having <code>content-box</code> as the value of
<code>box-sizing</code> means that when you set dimensions, such as a
<code>width</code> and <code>height</code>, they will be applied to the
<strong>content box</strong>. If you then set <code>padding</code> and
<code>border</code>, these values will be added to the content box's size.
</p>
<p>
The actual width of this box will be 260px. As the CSS uses the default
<code>box-sizing: content-box</code>, the applied width is the width of the
content, <code>padding</code> and <code>border</code> on both sides are
added to that. So 200px for the content + 40px of padding + 20px of border
makes a total visible width of 260px.
</p>
<p>
You <em>can</em> control this, though, by making the following modification
to use the alternative box model, <code>border-box</code>:
</p>
<pre
class="language-css"
><code class="language-css"><span class="highlight-line"><span class="token selector">.my-box</span> <span class="token punctuation">{</span></span><br><mark class="highlight-line highlight-line-active"> <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span></mark><br><span class="highlight-line"> <span class="token property">width</span><span class="token punctuation">:</span> 200px<span class="token punctuation">;</span></span><br><span class="highlight-line"> <span class="token property">border</span><span class="token punctuation">:</span> 10px solid<span class="token punctuation">;</span></span><br><span class="highlight-line"> <span class="token property">padding</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span></span><br><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
<p>
This alternative box model tells CSS to apply the <code>width</code> to the
border box instead of the content box. This means that our
<code>border</code> and <code>padding</code> get <em>pushed in</em>, and as
a result, when you set <code>.my-box</code> to be <code>200px</code> wide:
it actually renders at <code>200px</code> wide.
</p>
<p>
Check out how this works in the following interactive demo. Notice that when
you toggle the <code>box-sizing</code> value it shows—via a blue
background—which CSS is being applied <em>inside</em> our box.
</p>
<figure>
<div style="height: 650px; width: 100%">
<iframe
src="https://codepen.io/web-dot-dev/embed/oNBvVpM?height=650&theme-id=light&default-tab=result&editable=true"
style="height: 100%; width: 100%; border: 0"
title="Pen oNBvVpM by web-dot-dev on Codepen"
></iframe>
</div>
</figure>
<pre
class="language-css"
><code class="language-css"><span class="token selector">*,<br>*::before,<br>*::after</span> <span class="token punctuation">{</span><br> <span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span><br><span class="token punctuation">}</span></code></pre>
<p>
This CSS rule selects every element in the document and every
<code>::before</code> and <code>::after</code> pseudo element and applies
<code>box-sizing: border-box</code>. This means that every element will now
have this alternative box model.
</p>
<p>
Because the alternative box model can be more predictable, developers often
add this rule to resets and normalizers,
<a href="https://piccalil.li/blog/a-modern-css-reset" rel="noopener"
>like this one</a
>.
</p>
<h2 id="resources">
Resources <a class="headline-link" href="#resources">#</a>
</h2>
<ul>
<li>
<a
href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model"
rel="noopener"
>Introduction to the box model</a
>
</li>
<li>
<a
href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools"
rel="noopener"
>What are browser developer tools?</a
>
</li>
</ul>
<h3 id="user-agent-stylesheets">
User agent stylesheets
<a class="headline-link" href="#user-agent-stylesheets">#</a>
</h3>
<ul>
<li>
<a
href="https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css"
rel="noopener"
>Chromium</a
>
</li>
<li>
<a
href="https://searchfox.org/mozilla-central/source/layout/style/res/html.css"
rel="noopener"
>Firefox</a
>
</li>
<li>
<a
href="https://trac.webkit.org/browser/trunk/Source/WebCore/css/html.css"
rel="noopener"
>Webkit</a
>
</li>
</ul>
</div>