The CSS Box model
Tags: beginners, css
Published: 2019-11-04 23:13:35

---
title: The CSS Box model
published: true
description: A beginners guide to the CSS Box model
tags: beginners, css
series: FrontEnd Development Zero to Hero
---
HTML elements are treated as _boxes_ in CSS and the manner and way these elements are arranged on a web page are governed by the _CSS box model_ which is a _set of rules that define how web page are rendered_.

Having a good understanding of the _box model_ will aid you in creating your desired layout. 

Now, you might ask: _How come an HTML element is treated as a box in CSS_?

_Create your HTML and CSS files to follow along. Make sure your CSS file is properly linked with the HTML. If you have read previous posts in this series, you should know by now that all HTML code snippets will be inside the `body` tag._

Given the code snippets below:

```html
<h1>Header 1</h1>
<h2>Header 2</h2>
<div>
 <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit aliqua.</p>
</div>
  <ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
  </ul>
  <span>Lorem ipsum dolor sit amet, consectetur adipi</span>
  <span>Lorem ipsum dolor sit amet, consectetur adipi</span>
```
```css
* {
  outline: 3px solid #1560bd;
  margin-bottom: 1.5em;
  background-color: #f9f9fa;
}
```
Save your files and load the HTML in your browser.

![Block level elements in CSS](https://thepracticaldev.s3.amazonaws.com/i/0yg75lwuynu5h1yjvm39.PNG)

From the image above It's evident that elements appear in rectangular shapes, with some element spanning the entire width of the page e.g `h1`, `li` and some occupying just a fraction of the page e.g the `span` element. Why? you might ask.

In CSS these boxes are classified into two:

* block boxes 
* inline boxes

####__BLOCK BOXES__
If a box is defined as a block, it will extend in the inline direction to fill space available in its container (i.e its parent) and the elements that generate this type of boxes are called _block level  element_. Examples include `div`, `h1`, `li` e.t.c. Some other characteristics of these boxes are:

* They will break into a new line if need be.
* Their width and height properties will apply
* Padding, margins, and the border will cause other elements to move away from the box

This behavior of block boxes can be changed in CSS with the `display` property which accepts values like `inline`, `flex`, `grid`. Let's take an example.

Update your CSS to match the snippets below:

```css
* {
  outline: 3px solid #1560bd;
  margin-bottom: 1.5em;
  background-color: #f9f9fa;
  display: inline; /* Add this */
}
```

Save and Refresh your browser, all page elements will be rendered on a single line and will break into a new line if the available space is not enough.

![Block level elements acting like inline-level elements](https://thepracticaldev.s3.amazonaws.com/i/kyu09ircc5vknjfb1por.PNG)

####__INLINE BOXES__
As their name suggests these boxes will be rendered on a line and by default the width and height properties will not apply. Other behaviors of these boxes include:

* Padding or margin will not cause other elements to move away from the box
* They will not break into a new line

Just like block boxes, inline box behavior can be changed using the `display` property.

Add a `class` attribute to the `span` elements in your HTML:

```html
<span class="block">The first SPAN element</span>
<span class="block">The second SPAN element</span>
```

Update your CSS to with the snippet below:

```css
span.block {
  display: block;
  outline: 3px solid red;
}
```

Save your files and refresh your browser.

![The span element with the display property set to block](https://thepracticaldev.s3.amazonaws.com/i/279jultfhrvnrxw15itd.PNG)

The `display: block` can be applied to other inline elements like `a` (link), `em` , `strong` e.t.c.

With that out of the way, these boxes in CSS are made of four main parts. They are:

* Content
* Padding
* Border
* Margin

#####__CONTENT__
The is the text, images, or other media content contained in the element.

#####__PADDING__
This is an internal spacing that exists between the boundary of the element and the element's edge. And the element edge itself can have a border. Confused? Let's code.

Update your HTML and CSS to match the following snippet:

```html
<header>
  <h1>THIS IS H1</h1>
</header>
```
```css
header {
  border: 2px solid #1560bd;
}

h1 {
 padding: 2em;
}
```

Save your files. Refresh your browser, and perform the following steps:

* Use "Inspect Element" on the `h1` element
* Navigate to the __Layout__  tab
* Click on the _Box Model_
* Hover your mouse (or pointing device) over the inner purple box
   * the browser will let you know it's the padding and the corresponding element will be highlighted on the web page.

![Padding on page element](https://thepracticaldev.s3.amazonaws.com/i/50llog9ib0la9h5b69y6.PNG)

From the box model, you will observe that the padding value is applied to all four sides of the box. Why is this happening? That's because the `padding` property is actually shorthand for:

* `padding-top`
* `padding-bottom`
* `padding-right`
* `padding-left`

And it gets interesting, if you supply _two values_ to the `padding` property, the browser will use the _first value for the top and bottom_, and the _second value_ for the _right and left_. Say What?

```css
h1 {
  padding: 2em 2em;
}
```
But what happens if we supply _three values_? the _first value_ will be used for the _top_, the _second value_ will be _used for the right and left_, and the _third value_ will be _used for the bottom_.

```css
h1 {
  padding: 2em 3em 2em;
}
```

You can use the browser Developer Tools to confirm this:

![Padding with three values applied to an element](https://thepracticaldev.s3.amazonaws.com/i/hmeb9etx74ddmzs8rnh0.PNG)

#####__BORDER__
The is the line between the box’s padding and margin. For a code sample, check the code in the explanation on padding (specifically the `border` property declaration of the `header` element).  Repeat the steps to show the _Box Model_, but this time hover your mouse (or pointing device) over the area that's colored black. This is the border, the browser will do the rest

![The border in Firefox Developer Tools](https://thepracticaldev.s3.amazonaws.com/i/tjfvvuqaji7jeu6s6lko.PNG)

Just like the padding property, the `border` can be used to declare all four sides of the border at once. The sides are:

* `border-top`
* `border-right`
* `border-bottom`
* `border-left`

But unlike padding, you cannot declare different border width of all four border sides with the `border` property, you will have to explicitly change each side border width. This means 

```css
header { 
 border: 1px solid green; /* this is valid */
}
```

__IS NOT THE SAME AS__

```css
header { 
 border: 2px 3px solid green; /* this is invalid */
}
```

You will have to do this instead:

```css
header {
  border-top: 3px dashed green;
  border-right: 1px solid red;
  border-bottom: 5px solid gold;
  border-left: 4px solid maroon;
}
```

#####__MARGIN__
The margin controls the space between different elements on a page. Repeat similar steps as the explanation on border and padding, but in this case, you should hover your mouse (or pointing device) over the yellow area, this is the margin.

The `margin` property is also short for four other properties:
* `margin-top`
* `margin-right`
* `margin-bottom`
* `margin-left`

The margin property behaves similarly to the `padding` property and you can supply _one_, _two_ or _three_ values and the browser will do the rest.

![The margin shown in Firefox Developer Tools](https://thepracticaldev.s3.amazonaws.com/i/b6pz8ieb0fqeokzwkp3e.PNG)

_This parts (content, padding, border, and margin) apply to block-level elements and inline elements with the `display`  property set to `block`_.

These parts are summed up in the image below:

<figure>
![The Box model](https://thepracticaldev.s3.amazonaws.com/i/1c5mk21w3besf7d8ow98.png)
<figcaption>&copy; Wikipedia</figcaption>
</figure>

The paddings, borders, margins and the content of an element allow the rendered box to occupy a specific width and height on the page, most of the time you will have to know how to calculate the width and height of an element to make sure your web page is displayed correctly in all browsers.

When it comes to this calculation you should have it in mind that there are two box models in CSS. They are: 

* The standard box model
* The alternate box model

####__THE STANDARD BOX MODEL__
From the [Mozilla Developer Network]( https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model):

> In the standard box model, if you give a box a width and a height, <u>this defines the width and height of the __content box__</u>_. Any padding and border is then added to that width and height to get the total size taken up by the box

__This translates to__: In the _standard box model_ if you define a width and height for an element it becomes the height and width of the _content box_. What is the content box?

The _content box_ is the box that contains the content of a page element. For example if you have the following HTML:

```html
<p>This is a paragraph</p>
```
The content will be the phrase _"This is a paragraph"_. You can use the browser Developer Tools to confirm this. If you have your HTML opened in your browser, perform the following steps:

* Use "Inspect Element" on a paragraph element
* Navigate to the  __Layout__ tab
* Click on the _Box Model_
* Hover your mouse (or pointing device) over the innermost part of the box (the blue part)
* The Developer Tools will show the word _content_ and the corresponding content will be highlighted on the page.

![The content of an element shown in the box model](https://thepracticaldev.s3.amazonaws.com/i/juopp60en72ye7yeg1s9.PNG)

Now, let's take an example to show how the browser performs its calculation in this box model.

Update your HTML and CSS to match the following snippets.

```html
<div class="box">
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
```
```css
.box {
  width: 350px;
  height: 150px;
  margin: 25px;
  padding: 25px;
  border: 5px solid #1560bd;
}
```
Looking at the snippet above, _How much space will our box take?_ If you answered `350`, am sorry, it's not the correct answer, but you are definitely close.

The element will take up the space of `410px` and a height of `210px`. How?

Save your files and refresh your browser. Use "Inspect Element" on the paragraph, and navigate to the __Layout__ tab and click on the _Box Model_, you should have an output similar to the image below.

![Box model calculation show in Firefox developer tools](https://thepracticaldev.s3.amazonaws.com/i/0a5iq8np0txj04w34krt.PNG)

How did the browser arrive at this value(s)? If you take your time and observe, you'll figure it out. But all the same, time for some math.

To measure _how wide_ our element is, we start calculating from the _left border_ to the _right border_. Now observe the image below:

![Box model calculation show in Firefox developer tools](https://thepracticaldev.s3.amazonaws.com/i/utryk54cavafk28whzg9.PNG)

When you sum the highlighted value from the image above:

* _5 + 25 + 350 + 25 + 5_ => _410_ (the width value computed by the browser)

To calculate the _height_, we start from the top border to the bottom border.

![Box model calculation show in Firefox developer tools](https://thepracticaldev.s3.amazonaws.com/i/x5nm3sjknyid4c59oqna.PNG)

Summing up the highlighted value in the image above:

* _5 + 25 + 150 + 25 + 5_ => _210_ (the height value computed by the browser)

In some cases, you might not want the default standard box model calculations. Which brings us to the _alternate box model_.

####__THE ALTERNATE  BOX MODEL__
The alternate box model was introduced sometime after the standard box model.  Using this model, _any width is the width of the visible box on the page_, therefore the _content area width is that width minus the width for the padding and border_. Say What? Take a deep breath. Exhale. Now read on.

This _alternate box model_ is __not enabled by default__ compared to the _standard box model_ which is the __default model used in web browsers__.

To use the alternate box model, you will have to tweak your CSS with the `box-sizing` property.

Update your CSS to match the snippet below.

```css
.box {
  width: 350px;
  height: 150px;
  margin: 25px;
  padding: 25px;
  border: 5px solid #1560bd;
  box-sizing: border-box; /* Add this */
}
```
Save your file, and refresh your browser. Perform the usual step to show the _Box model_ in the Developer Tools and you should have an output similar to the image below.

![Box model calculation show in Firefox developer tools](https://thepracticaldev.s3.amazonaws.com/i/uk7kh6h03ppzmyfgavav.PNG)

If you sum up the highlighted values in the box you will get the same `width` value computed by the browser.

The browser is now using the width and height values we explicitly specified in our CSS i.e `350px`  and `150px`. Why? When you  declared  the `box-sizing` property with a value of `border-box`  you are telling the browser:

> to take the border box as the area defined by __any size you set__.

The border box is _the area from the left border to the right border_. And the browser gladly obeyed, by using the width specified in our CSS.

Using the _alternative box model_ is a common choice among developers (myself included) and to make it work for all elements in the web page, we'll have to set the `box-sizing` on the `html` element and set all other elements to inherit that value as depicted in the snippet below.

```css
html {
  box-sizing: border-box;
}

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

__ASIDE__: _Internet Explorer used to default to the [alternative box model](https://www.jefftk.com/p/the-revenge-of-the-ie-box-model), with no mechanism available to switch_.

We talked about margins in this post, but there is a gotcha that you need to watch out for, and that is the concept of _Margin Collapsing_. That's next.