The Box Model

Work in progress in a draft area of the wiki - please do not edit!

Everything in CSS has a box around it, and understanding these boxes is key to being able to create layouts with CSS, or to align items against other items. In this lesson we will take a proper look at the CSS Box Model, in order that you can move onto more complex layout tasks with an understanding of how it works and the terminology that relates to it.

Prerequisites: Basic computer literacy, basic software installed, basic knowledge of working with files, HTML basics (study Introduction to HTML), and an idea of How CSS works (study the previous articles in this module.)
Objective: To learn about the CSS Box Model, what makes up the box model and how to switch to the alternate model.

Types of box

In CSS we have two types of box, block boxes and inline boxes. They have different characteristics, which you need to understand when applying CSS to them. The type of box applied to an element is defined by the display property and relates to the outer value of display, or how the box behaves in terms of page flow, and in relation to other boxes on the page.

Inner and Outer Display Types

Without going into too much detail here, it is useful to understand that boxes in CSS have an outer display type, which details whether the box is block or inline. Boxes also have an inner display type, which dictates what happens to things inside that box. For example if I make an element display: block, then I am stating I want the outer display type to be block. If I use display: flex then the outer display type is block (display: flex is really display: block flex) and the inner display type is flex layout.

Note: to read more about the values of display, and how boxes work in block and inline layout, take a look at the MDN guide to Block and Inline Layout.

When you move on to learn about CSS Layout, you will encounter the various different types of inner values that your boxes can have, for example flex and grid layout. Block and inline layout however is the default way that things on the web behave It is sometimes referred to as normal flow, because without any other instruction, our boxes lay out as block or inline boxes.

Therefore in this lesson we really care about the outer display type, as this tells us how the box is going to behave alongside other boxes in our layout.

If a box is defined as a block, it will behave in the following ways:

  • The box will extend in the inline direction to fill the space. In most cases this means that the box will become as wide as the container, filling up 100% of the space available.
  • The box will break onto a new line
  • The width and height properties are respected
  • Padding, margin and border will cause other elements to be pushed away from the box

Unless we decide to change the display type to inline, elements such as headings and paragraphs all use block as their outer display type by default.

If a box has an outer display type of inline, then:

  • The box will not break onto a new line
  • The width and height properties will not apply
  • Padding, margin and borders will apply but will not cause other inline boxes to move away from the box

The <a> element, used for links, <span>, <em> and <strong> are all examples of inline elements.

Examples of block and inline layout

Let's have a look at some examples. Below I have three different HTML elements, all of which have an outer display type of block. The first is a paragraph, which has a border added in CSS. The browser renders this as a block box, so the paragraph begins on a new line, and expands to the full width available to it.

The second is a list, which is laid out using flexbox display: flex. This establishes flex layout for the items inside the container, however the list itself is a block box and like the paragraph takes full width and breaks onto a new line.

Below this I have a block level paragraph, inside the paragraph are two span elements. These elements would normally be inline, however one of the elements has a class of block, and I have set it to display: block.

 

We can see how inline elements behave in this next example. The spans in the first paragraph are inline by default and so do not force line breaks.

I also have a <ul> which is set to display: inline-flex, creating an inline box around some flex items.

Finally I have two paragraphs both set to display: inline. The inline flex conatiner and paragraphs all run together as one line, rather than beaking onto new lines as they would do if they were displaying as block level elements. In the example you can change display: inline to display: block or display: inline-flex to display: flex to toggle between these display modes.

 

You will encounter things like flex layout later in these lessons, the key thing to remember now is that changing the value of the display property can change whether the outer display type of a box is block or inline. This then changes the way it displays alongside other elements in the layout.

What is the CSS box model?

The full CSS box model applies to block boxes, inline boxes only use some of the behavior defined in the box model. The model defines how the different parts of a box - margin, border, padding and content - work together to create a box that you can see on the page. To add some additional complexity, there is a standard and an alternate box model.

Parts of a box

Making up a block box in CSS we have the:

  • content box: the area where your content is displayed
  • padding box: padding sits around the content as white space
  • border box: the border box wraps the content and any padding
  • margin box: the margin is the outermost layer, wrapping the content, padding and border as whitespace between this box and other elements

The below diagram shows these layers.

Diagram of the box model

The standard CSS Box Model

In the standard box model, if you give a box a width and a height, this defines the width and height of the content box. Any padding, border and margin is then added to that width and height to get the total size of the box. This is shown in the image below.

If we assume that the box has the following CSS defining width, height, margin, border and padding:

.box {
  width: 350px;
  height: 150px;
  margin: 25px;
  padding: 25px;
  border: 5px solid black;
}

The width taken up by our box using the standard box model will actually be 410px, and the height 210px, as the padding and border are added to the width used for the content box.

Showing the size of the box when the standard box model is being used.

The alternate CSS Box Model

You might think it is rather inconvenient to have to add up the border and padding to get the real size of the box, and you would be right! For this reason, CSS has an alternate Box Model. Using this model, any width is the width of the visible box on the page, therefore the content area is that width minus the width for the padding and border. The same CSS as used above would give the below result.

Showing the size of the box when the alternate box model is being used.

By default browsers use the standard box model. If you want to turn on the alternate model for an element you do so by setting box-sizing: border-box. By doing this you are telling the browser to take the border box as the thing defined by any size you set.

.box { 
  box-sizing: border-box; 
} 

If you want all of your elements to use the alternate Box Model, and this is a common choice by developers, set the box-sizing property on the HTML element. The before and after pseudo-elements are added along with a universal selector, setting the value to inherit. If you want to understand the thinking behind this, see the CSS Tricks article on box-sizing.

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

Note: an interesting bit of history is that Internet Explorer used to default to the alternate Box Model with no standard way to switch.

Playing with box models

In the below example, you can see two boxes. Both have a class of .box which gives them the same width, height, margin, border and padding. The only difference is that the second box has been set to use the alternate Box Model.

Can you change the size of the second box (by adding CSS to the .alternate class) to make it match the first box in width and height?

 

Use browser DevTools to view the box model

Your browser developer tools can make understanding the Box Model far easier. If you inspect an element in Firefox DevTools, you can see the size of the element plus margin, padding and border. Inspecting an element in this way is a great way to find out if your box is really the size you think that it is!

Inspecting the box model of an element using Firefox DevTools

Margins, padding and borders

You've already seen the margin, padding and border properties in the example above. The properties used in that example are shorthands and allow us to set all four sides of the box at once. These shorthands represent longhands allowing control over the different sides of the box individually.

Margin

The margin is an invisible space around your box. It pushes other elements away from the box. Margins can have positive or negative values. Setting a negative margin on one side of your box could cause it to overlap other things on the page. Whether you are using the standard or alternate box model, the margin is always added on after the size of the visible box has been calculated.

For margin we have four longhand properties:

In the example below try changing the margin values and see how the box is pushed around due to the margin creating or removing space (if it is a negative margin) between this element and the containing element.

 

Margin collapsing

A key thing to understand about margins is the concept of margin collapsing. If you have two elements whose margins touch, those margins will combine to become one margin. In the example below I have two paragraphs. The top paragraph has a margin bottom of 50 pixels. The second paragraph a margin top of 30 pixels. The margins have collapsed together so the actual margin between the boxes is 50 pixels and not the total of the two margins.

You can test this by making the margin top of paragraph two 0. The visible margin between the two paragraphs will not change, it retains the 50 pixels set by the bottom margin of pararaph one.

 

There are a number of rules that dictate when margins do and do not collapse. For further information see the detailed page on mastering margin collapsing. The main thing to remember today is that margin collapsing is a thing that happens, if you are creating space with margins and don't get the space you expect, this is probably what is happening.

Borders

The border is drawn between the margin and the padding of the box. If you are using the standard box model, the size of the border is added to the width and height of the box. If you are using the alternate box model then the size of the border makes the content box smaller as it takes up some of that available width and height.

For borders, there are a number of properties, because the border property sets the style, width and color of a border and there are four sides to the box and so four sides we might want to set borders on individually. To deal with each side individually but set width, color and style, use:

Then longhands to set all sides but deal with the color, style and width individually:

And longhands to set all of the different properties for each side individually!

In the example below I have used various shorthands and longhands to create borders. Have a play around with the different properties to check that you understand how they work. The MDN pages for the border properties give you information about the different styles of border you can choose from.

 

Padding

The padding sits between the border and the content area. You cannot have negative amounts of padding so the value must be 0 or a positive value. Any background applied to your element will display behind the padding, so it is typically used to push the content away from the border.

As with margin there are four longhand values for padding:

If you change the values for padding on the class .box in the example below you can see that this changes where the text begins in relation to the box.

You can also change the padding on the class .container, which will make space between the container and the box. Padding can be changed on any element, and will make space between the border and whatever is inside that element.

 

The box model and inline boxes

All of the above applies fully to block boxes. Some of the properties can apply to inline boxes, such as those created by a <span> element.

In the example below I have a <span> inside a paragraph and I have applied a width, height and margin, border and padding to it. You can see that the width and height are ignored. The margin, padding, border are respected but they do not change the relationship of other content to our inline box and so the padding and border is overlapping other words in the paragraph.

 

Using display: inline-block

There is a special value of display which can give you a middle ground between inline and block elements. This is useful for situations where you do not want an item to break onto a new line, but do want it to respect width and height and avoid the overlapping seen above.

An element with display: inline-block does a subset of the block things we already know about:

  • The width and height properties are respected
  • Padding, margin and border will cause other elements to be pushed away from the box

It does not however break onto a new line, and will only become larger than required for its content if you add width and height properties.

In this next example I have used this value on our span - adding display: inline-block. Try changing this to display: block or removing the line and see the difference in display models.

 

Where this can be useful is when you want to give a link a larger hit area by adding padding. A link is an inline element like our span, you can add padding then use display: inline-block to cause the padding to be respected, making it easier for someone to click the link.

You see this fairly frequently in navigation bars. My navigation below is displayed in a row using flexbox and I have added padding to the <a> element as I want to be able to change the background color on hover of the a. The padding appears to overlap the border on the <ul> element. This is because the <a> is an inline element.

Add display: inline-block to the selector .links-list a, and you will see how it fixes this issue by causing the padding to be respected by other elements.

 

Summary

That's most of what you need to understand about the box model. You may want to return to this lesson in the future if you ever find yourself confused about how big boxes are in your layout.

Next we will move onto looking at Writing Modes and Direction in CSS. What happens if you writing mode is something other than top to bottom and left to right?

Document Tags and Contributors

Contributors to this page: rachelandrew, chrisdavidmills
Last updated by: rachelandrew,