SITERAW

The CSS box model

Let's start with the first question you might ask yourself at the sight of this chapter's title: what is a box model?

Perhaps you've realized it already, every HTML element can be represented by a two dimensional rectangular box.

In fact, if you look back at the previous chapters, almost all of my diagrams and illustrations conveniently contained at least one such box.

The CSS box model essentially illustrates the fact that a web page can be seen as a succession and stack of multiples "boxes" sometimes also called blocks.

In this chapter we will learn how to interact with these boxes by giving them specific dimensions, placing and aligning them where we want on our page, handling their margins and much more.

These are the basic concepts we need to give our website a true design.

Block and inline elements

We've already talked about this distinction before so this will purely be a short review of what we already know.

Most HTML tags belong to one o two categories.

They can be either:

  • block elements such as paragraphs (<p>)
  • inline elements such as links (<a>)

In addition to those two there are also several less common level types such as flex or inline-block and even more specific types such as table-cell for tables cells and list-item for each item of a list.

Not only are they less frequently used but they can also be considered variations of either the block or inline type.

Inline and block elements
Inline and block elements

So for now you only need to remember the difference between block and inline elements.

But how do I know which ones are block or inline elements?

Very easily.

  • Block elements always start on a new line and take up the full width available.
  • Inline elements don't force a line break and take up only as much width as necessary.

Inline elements are always contained within block elements, which can in turn either be placed next to other blocks or even nested within them.

For visualization purposes, this is the behavior of an inline element.

An inline element
An inline element

And this is the behavior of a block element.

A block element
A block element
Every HTML tag has a default level type, usually block or inline, but you must remember that these are CSS display behaviors and can therefore be adjusted with the CSS language. We can very easily display links as block elements instead of their default inline, and vice-versa for paragraphs or titles. In fact, we'll learn how to do just that further on in this chapter.

General purpose tags

We already presented these tags in the Setting up CSS chapter so once again this will simply be a review.

There are two general purpose tags that you must be aware of in the HTML language, <div> and <span>.

The purpose behind these tags is that they carry no semantic meaning, unlike <p> for paragraph or <em> for emphasis.

Given that the entire point of the HTML language is to convey semantic information to the user agent this would seem about as useful as a foam hammer, but they are in fact used quite extensively in conjunction with CSS.

Imagine that you need to select a determined portion of HTML content purely for cosmetic reasons.

All you need is to apply one of these tags to the desired content and apply a CSS style, often with the class (or id) selector.

Yes, we already know that! So what is the difference between <div> and <span> ?

Coincidentally, the only variation between the default display behavior of the two is that <div> is a block element and <span> is an inline element.

I'll repeat myself, these are simply default behaviors and can be changed in CSS (although in this case it would make little sense to do so).

  • <div> : a block element
  • <span> : an inline element

As a last point that bears reiterating, these are generic tags that carry no semantic signification.

As such you should only use them when you want your elements to... carry no semantic signification.

When there is a more appropriate HTML tag available, use it.

Dimensions in CSS

Now that were done recapitulating the distinction between block and inline elements let's get back to our box model.

Let's start with the dimensions of our boxes.

Unlike inline elements whose dimensions are determined dynamically based on the content inside them, block elements tend to have a specific width and height.

Unsurprisingly, CSS provides us the following two properties.

  • width : the width of the element or width of the block
  • height : the height of the element or height of the block

The values defined can be either absolute, such as with the pixel unit, or relative, such as with percentages.

The width

If left unspecified, blocks will fill the entire horizontal area available to them.

In other words they will have a width value of 100%.

Blocks occupy all available width
Blocks occupy all available width

Thanks to these properties we can change the dimensions of our block elements, for example the paragraphs.

Try this code.

p { width: 50%; }

The result is shown below.

A paragraph with 50% width
A paragraph with 50% width

As you can see the width of the paragraph has been halved: it will now take up 50% of its maximum horizontal size.

When working with relative sizes such as percentages, it's important to remember that the size value of an item is based on the dimensions of its parent element.

This is particularly relevant in the case of nested tags.

Take the following code.

div { width: 50%; }

div p { width: 50%; }

Both the <div> element and the paragraph contained within it have their respective widths set to 50%.

And yet, here is the result.

A paragraph inside another block
A paragraph inside another block

What happened?

When you apply a relative value to the dimensions of one of your blocks, the actual size will be determined according to the dimensions of the parent element.

In our case the final width of the paragraph isn't 50% of the entire page, but 50% of the <div> element which itself takes up 50% of the page.

In other words 50% of 50% which makes it 25%, as shown in the example.

That seems overly complicated! Can't we just use regular lengths in pixels or inches?

It's actually very intuitive once you start seeing the design of web pages in terms of boxes.

Relative sizes are very useful for creating designs that automatically adapt themselves to the screen resolution of the visitor.

But to answer your question, it's entirely possible to specify an absolute length value rather than a relative size.

p { width: 250px; }

In this case the paragraphs will always be 250 pixels wide, irrelevant of the dimensions of the parent element or the user's screen size.

The height

Unlike for width where we had two different behaviors for block and inline elements, there is no such distinction with the height property.

All HTML elements will by default only fill as much vertical space as necessary.

A block element only expands to its parent's width but not to the parent's height.

This can lead to a few issues such as the following.

Different heights in CSS
Different heights in CSS

There is an obvious disparity in heights between the two elements.

How can we fix that?

It's just a matter of applying an identical value to the height property of both elements.

Let's try with this code.

p { height: 300px; }

This should fix the heights of our boxes.

Two elements with the same height
Two elements with the same height

This is particularly useful when you need to align several elements on the horizontal axis, such as with a menu bar or with equal height columns. Every item needs to have the same vertical size for the effect to work.

As with width, you can enter either an absolute or a relative value for the height property.

Minimum and maximum

In addition to what we just saw, you can also indicate a block's minimum and maximum dimensions with CSS.

This is only useful if you specify relative values for the height and width properties, otherwise the size doesn't change dynamically and there is therefore no distinct minimum and maximum.

There are four CSS properties you need to know of to achieve this effect.

  • min-height : the minimum height
  • min-width : the minimum width
  • max-height : the maximum height
  • max-width : the maximum width

Two for the minimum and two for the maximum.

Or two for the height and two for the width depending on how you choose to memorize them.

Here is how you can use these properties.

p
{
    width: 75%;
    min-width: 400px;
}

This code means your paragraphs should occupy 75% of the horizontal space available if possible, but always be at least 400 pixels wide.

Try changing the width of your browser window to see the effect in action (add a background color to the paragraphs to make them stand out).

The size of the block should follow that of the browser window until it reaches a certain minimum... 400 pixels.

Margins and padding

We know that every visible HTML element has a set of dimensions.

If you think of web design in terms of boxes, it makes sense to assume that the dimensions of one "box" are the same as the dimensions of the element it represents.

Let's take an example.

My paragraphs are 400 pixels wide. They are then displayed as 400 pixel wide boxes, right?

Right!

Wrong.

Why would that not be true? It doesn't make any sense!

It's not necessarily a false statement but it's certainly not always the case depending on several factors.

We already know one from one of our previous chapters: borders.

HTML elements may or may not have borders surrounding it.

So if the paragraphs are 400 pixels wide and the borders are 10 pixels wide on all sides, the total width of the "box" will be 420 pixels (10 + 400 + 10).

It's important to remember that dimensions in CSS are additive not subtractive.

The size of the box is not invariably that of the element it wraps around.

You also have to account for several other factors.

There are four parts that compose a CSS box: the content, its borders and its margins.

That's only three! Stop trying to teach us arithmetics if you can't even count.

That's because there are two types of margins in CSS.

There is an inner margin called padding and an outer margin that is mostly just called margin.

  • padding: the inner margin, between the content and the border
  • margin: the outer margin, outside of the border

If you need a more visual example look at the figure below.

Padding and margin in CSS
Padding and margin in CSS

We now know all four parts that compose the CSS box model.

In order, from the center to the periphery:

  • the content
  • the padding
  • the border
  • the margin

The dimensions of a block are the sum of those of these four components.

This is something to keep in mind when building the design of your web pages.

The padding

In CSS, the concept of padding refers to the "inner margin" that separates the content away from the edges of a block.

The property we will use is padding and it takes a standard length value, either relative or absolute.

Here is how it works.

p { padding: 35px; }

You can see the effect more clearly if you add a border and/or a background color to your elements.

The padding in CSS
The padding in CSS

The should notice a 35 pixel padding around your paragraph, between the content itself and the border if there is any.

But there is a padding on all sides! I just wanted one on the left and right.

Indeed, using the padding property will apply space to all four sides of the block.

The reason is that padding is not just a CSS property but a super-property or shorthand property.

As we've already seen them quite a bit by now I won't be going into to much detail on how they work, but you should know that super-properties allow you to combine multiple CSS properties into a single one.

The padding property we just saw is precisely that.

It merges the following four properties into one:

  • padding-top : the padding on top of the element
  • padding-right : the padding to the right of the element
  • padding-bottom : the padding on the bottom of the element
  • padding-left : the padding to the left of the element

Hence the following two codes producing the same result.

p { padding: 15px; }

p
{
    padding-top: 15px;
    padding-left: 15px;
    padding-bottom: 15px;
    padding-right: 15px;
}

The values for the padding of each different side don't need to be the same either.

You could just as well enter four separate values.

This is the order in which the values of each side should be specified.

padding: <top> <right> <bottom> <left>;

When dealing with shorthand properties and especially with value different geometrical points or sides in CSS, remember that the order is always a clockwise rotation starting from the top.

The padding shorthand property
The padding shorthand property

As with the border-radius property that we introduced a while back, there are other ways to entered the values of each side with padding.

You can for instance define only two values: the first for the top and bottom, the second for right and left.

Or you can just write a single value and it will be applied to every side, which is what we've been doing until now.

The figure below details these cases in more detail.

Differents ways to add padding in CSS
Differents ways to add padding in CSS

Whichever format you may need, always remember the order: clockwise and starting from the top.

The margin

What we call margin in CSS is the outer margin which separates the entire block, including any borders, from other elements outside of it.

The property to do so is naturally called margin.

It's used much in the same way as padding so we won't go through every single one of its applications.

For example, if you waned to add a 35 pixel outer margin to your paragraphs you would write the following.

p { margin: 35px; }

Margins are used separate each element from one another as shown below.

The margin in CSS
The margin in CSS

If you only need to add margins to a specific side you can use one of the following properties.

  • margin-top : the margin on top of the element
  • margin-right : the margin to the right of the element
  • margin-bottom : the margin on the bottom of the element
  • margin-left : the margin to the left of the element

You can also use the abridged form of the shorthand property.

margin: <top> <right> <bottom> <left>;

A few examples.

Differents ways to add margins in CSS
Differents ways to add margins in CSS

You should be familiar with this method by now, it works in the exact same way as with padding.

The order is always the same: clockwise and starting from the top (top, right, bottom, left).

You now know everything you need about CSS box models.

  • Each HTML element can be represented by a box.
  • These boxes all have dimensions.
  • The dimensions of one box are the sum of those of its element's content, padding, borders and margins.

A quick test to evaluate your knowledge.

Have a look at the following code.

p
{
    width: 500px;
    padding: 25px;
    border: 3px solid red;
    margin: 20px;
}

With what you've learned during this chapter, you should be able to tell me the exact value of the horizontal length of each box wrapping around the paragraphs.

Hopefully you didn't answer 500 pixel.

If you said 548 pixels, you're getting close but you're still retarded.

The correct answer was of course 596 pixels wide.

Remember that by default most properties apply to all sides, that includes left AND right.

It's easy to verify.

We know that a CSS box is the composed of four parts: the content, the padding, the border and the margin.

ComponentWidth
Content500 pixels
Padding(25 * 2) = 50 pixels
Border(3 * 2) = 6 pixels
Margin(20 * 2) = 40 pixels
Total596 pixels

A few more properties

You thought this chapter was over?

Admit it, you always fall for it.

Technically we've covered the essentials of the CSS box model and you should be by now more than accustomed to how they work.

But there are still a few noteworthy cases that warrant more explanations.

Switching between block and inline

You might wonder how you can render an inline element as a block or vice-versa.

As I mentioned previously, whether an element is inline or block is nothing more than default CSS behavior.

It can be easily modified and whichever value you specify will override the default level type.

The property you need is display and its value is the type of rendering box you want for your element.

For example, you can make your paragraphs inline and turn your links into blocks.

p { display: inline; }

a { display: block; }

What's the point, you may ask.

In this particular instance there really isn't any.

The default CSS rendering behavior was chosen for a reason, and it makes much more sense to have block paragraphs and inline links.

But the display property is nonetheless very important in CSS.

In addition to block and inline, and many other rendering box types, it can also take the value none to turn the element invisible.

This is convenient if you need to make an element dynamically appear for example when the user clicks on a checkbox.

p { display: none; }

The above code will make your paragraphs invisible to the user, although they will still show up in the source code.

Centering a block

You may want to have a block centered either to the rest of the web page or in relation to another element.

The method for doing so is the same, and we won't even need to learn any new property.

You only need two properties that we already learned about in this chapter.

  • width : to specify the width of the element
  • margin : to align the element to the center by setting the value to auto

When applied to the margin property, the auto value will provide automatic outer margins to the block.

In practice that will enable you to center your element horizontally.

For example.

p
{
    width: 300px;
    margin: auto;
}

This should give you a result that looks something like this.

A centered block with CSS
A centered block with CSS

If an item is nested within another element, it will of course be centered in relation to that element and not the rest of the HTML page.

Box sizing

Remember when I said that dimensions in CSS were additive rather than subtractive? Keep that in mind and we'll come back to it in a moment.

Since the dawn of CSS web designing, the box model has always worked as follows.

  • visible box: content + padding + border
  • total box: content + padding + border + margin

This can be a little counter-intuitive for beginners, as to determine the dimensions of the block rendered on screen you would have to add those of the content, the padding and the border while keeping in mind the the total allocated size would also include the outer margin.

The default CSS box model
The default CSS box model

But what if I told you there was a way to make the total dimensions subtractive instead?

This would simplify the box model considerably.

Rather than adding the dimensions of the padding and border to those of the content, you would simply subtract them.

This practice is considered a form of box sizing.

Here is an example.

Box sizing with CSS
Box sizing with CSS

The property you need to achieve this is box-sizing.

It can take the following two values.

  • content-box : the dimensions of the padding and border are added to those of the content (default)
  • border-box : the dimensions of the padding and border are subtracted from those of the content

Keep in mind that in both cases the dimensions of the outer margin are added to the total size of the box.

A simple demonstration with one of our previous examples.

p
{
    width: 500px;
    padding: 25px;
    border: 3px solid red;
    margin: 20px;
}

We already calculated the total size of the visible box which was 556 pixels wide (596 pixels if you count the margins).

But let's see what happens when we prepend and modify the box-sizing property.

p
{
    box-sizing: border-box;

    width: 500px;
    padding: 25px;
    border: 3px solid red;
    margin: 20px;
}

Now the total width of the visible box is only... 500 pixels (540 pixels if you count the outer margin).

How is that possible?

Because the width of the borders (3 + 3 = 6 pixels) and that of the padding (25 + 25 = 50 pixels) were subtracted, not added, to the width of the content.

Which means that the final value of the width property was automatically altered to be no longer 500 pixels, but 444 pixels (500 - 50 - 6).

Default vs box sizing
Default vs box sizing

As you can see from the figure above, the two methods will produce different results based nearly identical code.

Which method should I use?

It's once again a matter of preference.

The first method is more common simply by virtue of being the default option, but you should know how to switch from one to the other.

Overflowing content

When working with absolute dimensions such as pixels or inches, it may happen that the content overflows vertically or sometimes even horizontally.

The CSS property overflow was created specifically to check for overflowing content and determine what to do if such case were to occur.

It can take the following values which affect the CSS behavior in case of an overflow.

  • visible : the content will remain visible even outside the block limits (default)
  • hidden : the content will be clipped outside of the block limits
  • scroll : scroll bars will appear along the height and width of the content ensuring it doesn't overflow
  • auto : similar to above only the scroll bars will only be displayed if necessary (if the content overflows)

To give you a visual example.

Overflow in CSS
Overflow in CSS

Obviously none of these solutions are ideal, so it's always best to make sure that your content fits in the boundaries of the box or that you use relative dimensions.

Outlines

Finally, the CSS property outline allows you to add a "border" outside of both the padding and the actual border.

It's a shorthand property that works almost exactly like border.

You will certainly recognize the following syntax.

p { outline: <outline-width> <outline-style> <outline-color>; }

For example.

p
{
    border: 2px dashed black;
    outline: 5px solid red;
}

The following figure shows what outlines look like in CSS.

Outlines in CSS
Outlines in CSS

If you don't want the outline glued to the border you can also use the property outline-offset to indicate a distance between the outline and the edge of the element.

p
{
    border: 2px dashed black;
    outline: 5px solid red;
    outline-offset: 20px;
}

I said outline worked almost like border, and it's true except for three minor differences.

  • It always applies to all sides of an element (there is no outline-right for example)
  • It isn't affected by border-radius or other CSS properties altering border styles
  • Unlike borders, outlines aren't considered part of the box model so they don't change the dimensions of the element of adjacent elements
So what's their purpose?

Other than having cool double borders? It depends.

Outlines are often used to dynamically emphasize an element without affecting its positioning.

For example, adding a border upon a :hover might shift the element to one side or another if the horizontal dimensions of the border are asymmetrical.

Outlines on the other hand aren't dependent upon the box model, thus the element will remain in its original place.