Six Questions to Understand the CSS Box Model

Introduction

The box model is one of those concepts in CSS that confuse a lot of new front-end developers. Many of its implications were fuzzy to me. So this article is an attempt to understand more of the concept and also help others have a better idea of the box model.

In this article, we will explore the following six questions:

  1. What is the box model?
  2. What are the main properties of a box?
  3. What are the main types of boxes?
  4. How to calculate the dimension of the box?
  5. In what circumstances do margins collapse?
  6. When content overflows.

1. What is the Box Model?

The CSS box model is a set of rules that defines how every element in a web page is rendered. According to the box model, every element in a page is a rectangular box with at least a content, a width and a height.

According to the CSS box model, every element in a web page is a rectangular box. The content is in the middle, surrounded by optional elements such as padding, border, and margin. The box model has five main parts/properties that determine the size of the box. Those properties are the width, the height, the padding, the border, and the margin.

Apart from the width, height, the other properties are optional. Meaning that we can have a box with no padding, no border, and no margin. In the next section, we will detail the different parts of this box.

2. What are the Main Properties of the Box?

We will start by creating a basic html file with a paragraph of dummy text. Let’s call this file index.html. We will be using Brackets as our text editor. For styling purpose, let’s create an external CSS file and name it main.css.

Basic setup

We define width, height, padding, border, and margin for our paragraph. We can visualize the illustration of the box model in the browser with the Chrome Developer Tools.

Our paragraph as represented by the Chrome Dev Tools

The image below is the actual representation of the box. The margins are highlighted thanks to Brackets.

Our paragraph with the margin highlighted

Below, we have the same image without any highlight.

The actual look of our paragraph displayed in the browser

A box has generally five main parts including the width, height, padding, border, and margin. Width and height are mandatory, whether we set them or not. Padding, border and margin are optional.

Content, Width and Height

In every box, there is content in its core. The content can be text, images, videos, audio, etc. Width, height, padding, border, and margin apply to the content. Every html element has a default width based on two factors: whether the element is an inline or block element. The height is rarely set for elements. It is in general, the height of the content that is used as a default.

Padding

Padding is the space surrounding the content, separating it from the border. It takes the background color of the content. The padding CSS property is a shorthand for padding-top, padding-right, padding-bottom, and padding-left. It defines the size of the space between the content and the border, or the margin if the border is not set, e.g. non existent. We can apply padding to any HTML element. But, it can never have a negative value.

p {
padding: 50px;
}
A paragraph with a padding of 50px.

Border

The border is the line surrounding the content and the padding, and separating them from the margin. By default, it is set to zero and is not visible. The border property apply to the four sides of the box: top, bottom, left and right. It takes the color of the element unless we specify a color.

p{ padding: 50px; border: 15px solid blue;}

p {
padding: 50px;
border: 15px solid blue;
}
A paragraph with a padding of 50px and a blue border of 15px

Margin

Margin is generally the extra blank space around elements. Like padding and border, margin is optional and has a default value set to zero. In this case, it is not visible. Developers generally use margin to separates different boxes. By default, modern browsers use it for example to put a line break between paragraphs.

It is important to note that margin is the external space separating boxes. It is thus, not taken into account when determining the width or hight of an element.

Margin has four properties: margin-top, margin-right, margin-bottom, and margin-left. The shorthand for these properties is the margin property.

Margin of 30px is highlighted in blue. Notice the size of the margin between the 2 boxes.

Margin is always transparent. Meaning, it takes the background of the parent element. In the image above, the background color of the parent element is ANTIQUEWHITE, so is the background of the margin. We highlighted the margin area to help you envision its size.

3. What are the Main Types of Boxes?

Before diving into the box model details, it is necessary to distinguish the main types of boxes one can encounter when dealing with HTML and CSS. While there can be a large variety of boxes and sub-boxes, there are two main types: inline box or block box. Inline boxes can be non-replaced or replaced elements.

Inline Boxes

Inline boxes are laid out , from left to right and have generally no width or height applied to them. Unlike other types of boxes, inline boxes do not fill hundred percent of their parent width. It’s width is the width of the content of its element (text for example).

Also, two or more inline elements will stick one after each other, without a line break. Well-known inline CSS properties include “a”, “em”, “strong”, “span”, “q”, “textarea”, etc.

There are two types of inline elements: replaced and non-replaced elements. We will explore these two notions below.

  • Inline Replaced Elements

W3C defines replaced element as:

An element whose content is outside the scope of the CSS formatting model, such as an image, embedded document, or applet. For example, the content of the HTML IMG element is often replaced by the image that its “src” attribute designates. Replaced elements often have intrinsic dimensions: an intrinsic width, an intrinsic height, and an intrinsic ratio. For example, a bitmap image has an intrinsic width and an intrinsic height specified in absolute units (from which the intrinsic ratio can obviously be determined). On the other hand, other documents may not have any intrinsic dimensions (for example, a blank HTML document).

A replaced element is an inline element with an intrinsic width and height. Meaning that the width and height are not defined with CSS, but belongs to the element. For example, the initial width and height of an image is set outside of CSS.

The content of a replaced element is not in the document, it is generally a link to an external content. It is the case of the image tag which links to an external file.

Well-known replaced elements include the following:

<img>, <embed>, <video>, and <iframe>.

An image tag <img> links to an external file. This file can be a local one (in one of the website folders), or external to the website in which it is displayed. In this case, the file is generally hosted in another server (website, document sharing application, etc.).

Other replaced elements include <input>tag. This tag in itself has no content. The element is replaced either by a text, a radio, a checkbox, etc.

Although replaced elements can be manipulated by CSS, they have two main particularities:

  • we can't apply generated content to them; and
  • in absence of the CSS loading, they will load their default width and height.
  • Inline Non-Replaced Elements

An inline non-replaced element is an inline element that is not a replaced element. We will explore the main characteristics of inline non-replaced elements below. In the paragraphs below, we will refer to inline non-replaced elements as inline elements for simplicity.

Only left and right margin apply to an inline box. Also, while top and bottom padding can apply to an inline box, they will have no effect on the surrounding boxes but the background color.

In the example below, we will add a quote ( an inline element) inside a paragraph and apply width, margin and padding to it.

quote (inline element) with width, margin, and padding

The effect of our basic styling is shown below:

The first thing we notice is that the width property has no effect on the quote. So no need to apply width or height on inline boxes, at least as far as non-replaced elements are concerned.

In the image below, we have the same image with a ruler to have a better idea of the width of the horizontal white space surrounding the quote:

We can see that the total width of the white space at the right of the quote is approximately 60px. It is the combination of padding-left and margin-left which are 30px each.

With the two images, we can notice that padding and margin have no effect on the vertical sides of the quote. It is as if no top and bottom padding and margin was applied.

We can see that even if horizontal padding has no effect on the surrounding, applying a background color has an interesting effect.

The background color will apply to the element, including its top and bottom padding.

While vertical padding has no effect on the text surrounding our quote, things change if we apply a background color. The text above our quote element is completely hidden by the background color. For the text below, it’s another story. it is not useful to apply background color to an inline element with padding-top defined.. Unless we want to hide the text or element above the one we are applying the background. And here is no need applying padding-top at all to inline non-replaced elements.

Block Level Elements

Contrary to inline elements, block level elements act as if there is a line break after them so that they stack up one on another like actual boxes. Yet, there is a slight difference with actual boxes. Block level element occupy their space so that even if their width is less than the width of their parent container, by default, no other element will occupy the remaining vertical space. So they can have specific width and height, and padding, margin, and border on all four sides.

4. How to calculate the Dimension of the Box?

Various elements determine how we calculate the size of the box. At its core, we have the width and the height of elements. As mentioned above, an element has optional properties like padding, border, and margin.

The box model is related to the size of elements in a web page. We calculate the dimension of a particular box by taking into account the width , height, padding, border, and margin of the element. So, defining a width and a height was a part of the element dimension setting.

The width property defines the width of an element content. Padding and border are also added to the total width of the element.

p {
width: 200px;
padding: 10px;
margin: 10px;
border: 1px solid #eee;
}

In the above example, the total width of the paragraph is the combination of

width (200px)                              + 
padding-right (10px) + padding-left (10px) +
margin-right (10px) + margin-left (10px) +
border-right (1px) + border-left (1px).

The total width of the paragraph is actually 242px instead of 200px.

With CSS3 however, a new concept was introduced to make the calculation of the element width more intuitive: the box-sizing property.

The Box-sizing Property

The box-sizing property allows the developer to choose how to calculate the width of an element. There are three values associated to box-sizing: content-box, padding-box, and border-box.

Content-box: Content-box is the default. The element width does not include padding and border, so, they add up to the box dimension. As its name implies, the width include only the content. By default, the content in the box will keep the same width after we add padding or margin. This means that the box will get larger by taking into account the extra padding or margin.

Padding-box: The element width include padding, but not border. At the time of writing, only supported by Firefox. It is thus not recommended to use it.

Border-box: The last value brings more flexibility and makes the calculation of the element width more intuitive. The width of an element includes padding and border. Applying box-sizing of border-box to our previous example will lead to a total width of 200px. Width includes padding and border. The behavior we can notice here is the content shrinking down to allow padding and border within the same width.

Box Dimension Specificities for Block Level Elements

If we don’t specify a width for our content, it will take as much width as it will be allowed. Block elements nested in another block element like a div, will take 100% of its parent’s width if we don’t set a with for it. For illustration purpose, let’s consider the following configuration:

<div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nemo error culpa repudiandae tenetur laborum magni, corporis quae voluptate. Mollitia asperiores deleniti error perferendis atque, corporis id harum? Quaerat, autem, explicabo.<p>
</div>
div {
width: 800px;
background-color: bisque;
}

We have a paragraph inside a div element. The width of the parent element (div) is set to 800px and the p element has no explicit width. In this case, the width of the paragraph will default to 800px, another word, it will take 100% of its parent width.

The width of the paragraph defaults to the width of the parent element (800px)

The parent can sometimes be the window(body). In this case, its width is set to 100% of the screen window by default. In the case where we add padding to an element with no declared width, it takes 100% of its parent’s width. When we add padding to it, the width remains the same.

Using our previous example, let’s add a padding of 30px to our paragraph.

p {
padding: 30px;
}

The content of the element will shrink down to allow space for the padding. The total width of the paragraph remains at 800px even with the addition of 30px at left (padding-left) and 30px at right (padding-right). The same behavior will happen if we add border or margin

The width of the paragraph remains at 800px and the content shrinks down.

5. In What Circumstances Do Margins Collapse?

According to the W3C specifications,

“the expression collapsing margins means that adjoining margins (no non-empty content, padding, or border areas, or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.”

Collapsing margins occurs generally in two occasions. Between adjacent elements and between parent and child elements.

Collapsing Margins Between Adjacent Elements

With two paragraphs with a margin of 30px (top, right, bottom, and left), the vertical space between the two should be 60px. I mean the space where the bottom margin of the first paragraph and the top margin of the second one meet. Simple calculation: margin-bottom: 30px, for the first paragraph + margin-top: 30px, for the second paragraph = 60px.

But this is not what happens. The actual size between the two paragraphs is 30px, instead of 60px. As mentioned in the specs, the adjoining margins combine to form one. It is as if the top margin of the second paragraph has magically disappeared.

In the case where the bottom margin of the first paragraph and the top margin of the second one have different values, the largest value is applied. The small one is then ignored.

When one of the margin has a negative value, the two are added up and the sum of the two values is used.

Collapsing Margins Between Parent and Child Elements

Margin also collapse between parent and child elements that have no content, border, or any other element between them. Let’s create a div element inside which we have a nested paragraph. Here are the CSS for our two elements:

div {
margin: 30px 10px;
background-color: #ccc;
}
p {
margin-top: 20px;
background-color: #efe;
}

The HTML code is as follow:

With the top margin of the div and the paragraph set at 30px and 20px, the distance between the edge of the page and the paragraph should be 50px. But as with adjacent elements, the margins collapse and the highest one (margin of the div) is used to the detriment of the lowest (p).

We can prevent the collapsing of the margins by either setting a padding or border to the parent. In our example, we should apply padding or border to the top and the bottom to prevent the collapsing on top and bottom of the parent element.

It is also important to note that margins do not collapse when the parent has one of the following settings:

- position: absolute; 
- position: fixed;
- overflow: hidden; or
- overflow: scroll;

6. When Content Overflows

In the previous sections, we have discussed about the box and how the width is affected. In this section, we will discuss the behavior of the box when considering the height and the - content of the elements.

By default, an element takes as much height as its content fits if we do not declare a specific height. In this case, there is not so much to deal with. Things get trickier when we set a specific height for an element. We will discuss here the specific case when the content overflow. Meaning when the height of the content is larger than the specified height of the element.

For illustration, let’s create a paragraph with dummy text of 400 words and with the following CSS specifications:

p {
width: 800px;
height: 250px;
background-color: aqua;
}

The text as illustrated in the browser.

Text overflows the actual dimension of the paragraph, here with the colored background.

In CSS, there is a property called overflow that help deal with this case. The property has four values: visible, scroll, hidden, and auto. If we don’t define the overflow property, it is set to visible by default. So our previous example of the text overflowing out of the paragraph boundaries is an illustration of this default setting.

We will explain what each of these values uncovers, starting by ‘visible’.

overflow: visible

By default, a content is set to overflow: visible. Unless we want to override a previous declaration of overflow, there is no use setting it to visible.

overflow: hidden

p {
width: 800px;
height: 250px;
background-color: aqua;
overflow: hidden;
}

Sure enough, when overflow is set to hidden, any content above the defined dimension of the box will be hidden.

overflow: scroll

To have a better idea of the impact of setting overflow to scroll on a content, we will use our previous text and set overflow to scroll.

p {
width: 800px;
height: 250px;
background-color: aqua;
overflow: scroll;
}

Let’s check the effect on the text.

In the image above, we can notice the scroll bar at the top right. With this value, there is always a scrollbar.

overflow: auto

This value is almost similar to scroll, but with a slight difference. It gives a scrollbar only if it is needed.

Conclusion

There is a lot to write about the CSS box model. And as you can notice, this article has just scratched the surface. Other interesting points to explore include positioning and float in regard to the box model.