Building a static website (part 6: The CSS box model)

Published and updated date of webpage. 06-SEP-2025, updated 10-SEP-2025

In the previous blog post, I looked at the basics of responsive images. In this post, I want to try and understand one of the most important building blocks of styling pages with CSS, which is the "CSS box model". This is something that is fundamental to the way webpages are laid out, so it is something that I definitely need to understand. This might well be the first of a few posts about important CSS related topics, which will bring me closer to being able to design the look of the pages are planned for my website.

CSS box model basics

From the point of view of CSS, it seems that everything that is displayed on the web page is considered to be inside one or more boxes (usually, many boxes). They have a particular size and position, based on certain kinds of defaults or explicit rules, defined in the CSS. Often, the boxes are invisible.

However, the astute amongst you will have spotted that the previous two paragraphs and the subheading have some CSS settings that help to reveal some of what is going on behind the scenes. We can see that the <h2> and <p> HTML elements have a light blue background and are surrounded by a thin red border, whereas the <em> element has a yellow background, with a thin black border.

Importantly, there are two types of HTML elements/boxes, which have significant effects on the way that they are presented on a webpage, at least in their default form.

Having quickly summarised the basics, we can dive into some more of the details of the CSS box model, by considering the four properties that are defined for each box. The diagram below summarises this. Briefly, we have (working from the inside out):

CSS box model summary.

Now we can go into a few more details of the different box properties.

Content. Apart from the obvious importance of this being the semantically important information that we are presenting to the user, by default, if you set explicit dimensions for an HTML element, this actually sets the dimensions of the content area, with the other values (if any) added on top. I will come back to that later.

Padding. This is an area between the content and border of the box. Note that if a background colour is set for an element, it will cover both the content and padding areas. It also forms part of the "clickable area" of an element, if that is relevant.

Border. This can be specified as a decorative design element that appears round the visible portion of the HTML element. A typical CSS declaration might be: border: 1px solid red, which follows the pattern "size" "border style" "colour". In this case, the border will be a one pixel red solid colour border round the entire box.

Margin. This is an invisible area that surrounds the visible portions of an element and is generally intended to provide a separation between separate elements. It is essentially a buffer zone. It is excluded from the "clickable area" of an element, again where that is relevant.

For block elements, it has a behaviour distinct from the border, padding or content, which is referred to as "vertical margin collapse". Briefly: if there is a block level element that has a bottom margin set to be 50 pixels and directly below that is another block level element with its top margin set to be 30 pixels, the actual total space taken up vertically is 50 pixels (not the 70 pixels you might expect). The margins collapse together, so that the biggest margin value is retained. Naturally, it can be somewhat more complicated than that, but I understand that to be the general idea.

Note that to avoid unexpected margin collapse, I believe recommended technique is to only define bottom margin values for block level elements, which I do intend to make use of, but that's a subject to be covered in more detail at another time.

Box sizing

The size of boxes can be changed by various CSS properties, although the resultant behaviour depends on a number of things, including whether it is a block or in-line box and whether the "content box" or "border box" scheme is being used. The box-sizing property sets this.

Note that, while reading the descriptions below, bear in mind that the box margin value is not affected at all by the setting of the box-sizing property.

Content box

By default, if you specify a size for a block level element, by setting its width or height (or both), that size value will set the content size (hence the name). This means that if the element also has nonzero values set for the padding and/or border, those values will be added to the size of the content and hence the actual size of the box will be bigger than that specified. That is illustrated in the following diagram where it shows that the width is being explicitly set, but that the overall width is set automatically, to include the padding and border size.

This is the default, but if necessary can be set explicitly using box-sizing: content-box.

Content box: content width set explicitly, total box width set automatically.

Border box

In contrast, where the border box is being used, the size of the box as specified by the CSS applies to the entire elements box, including the border, which means that the content size is set automatically and if either/or border and padding have nonzero values, it will mean that the content area is smaller than the size specified.

This contrast in behaviour is illustrated in the following diagram, where once again we assume that we are setting width with CSS and in this case, it sets the size of the elements entire box, leading to the content area being set automatically.

In order to set this, we use box-sizing: border-box.

Border box: outer width set explicitly, content with set automatically.

I gather that border box is the favoured approach, despite the default being content box. The reason for this is that it can either be considered more intuitive or more predictable. If we set the size of a border box, we know exactly how big that box is going to be and that can be very useful, as opposed to constantly trying to take into account the values for padding and border. I guess that much of the time, the content area can easily cope with being squeezed in size, especially for text.

Going forward, I intend to adopt the border box setting. This should occur from the next blog post onwards.

CSS box alignment

Aligning and positioning of boxes is clearly very important and there are some (increasingly) sophisticated methods for doing so, including floats, flexbox and grid. However, there are a couple of straightforward alignment techniques that are likely to come in handy, so I'm going to quickly document them here.

Centre alignment

Centring a box within a page (or technically, within its containing element), is straightforward to achieve. I'm trying to make sure I remember this one, because it's something that I am quite likely to want to use.

For example, the following box is centred. The relevant CSS is included within the box. Note that it is required to set an explicit width for the box, otherwise there will be no noticeable effect. We use width: 300px. The other important part is margin: 20px auto. This sets a margin of 20 pixels, while the auto causes it to be centred within its parent element.

This box is centred, using the following CSS:

div.centered_box
{
   width: 300px;
   border: 5px solid blue;
   background: lightblue;
   margin: 20px auto;
}

It is also not difficult to align a similar box to the right hand side of the window, using the old float method. We can see that in the following example. Again, it is important to set an explicit width, otherwise it won't work. No surprise that the other important part of the CSS is the float: right.

This box is aligned to the right hand edge, using the following CSS:

div.box_align_right
{
   width: 300px;
   border: 5px solid blue;
   background: lightblue;
   margin: 20px auto;
   float: right;
}

Note that in the case of using float, subsequent elements will be aligned to the left of the box, until such time the float is cleared. This current paragraph is a demonstration of that, because it should indeed appear to the left-hand side of the box.

In order to prevent that continuing, you have to clear the float and in the case of this and subsequent paragraphs, I'm using a <div> element, with the CSS property of clear: both. That means that it now appears below the box.

In terms of using floats, that's probably about as much as I need to know I think, because the other, more modern layout features (flexbox and grid) are much more versatile. However, this kind of alignment might well come in handy for more straightforward cases.

A little bit of extra CSS

One thing that may have been noticeable is that I have started experimenting with some styling for what I would consider to be in line code, for example <picture> or width: 500px. I'm now marking these up with <code>, with various class definitions. I will be working on that further as the design process continues.

Conclusions and design decisions

Having a good understanding of the CSS box model appears essential for effective styling of webpages, so my only conclusion is that I now feel in a good position as far as that is concerned. In terms of concrete design decisions, there is not a great deal to say, except that I am intending to avoid vertical margin collapse problems by defining only a bottom margin for elements, which is part of a much wider approach to styling that I intend to look at in the next blog post.