Building a static website (part 6: The CSS box model)
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.
- Block element: these appear one after another on a webpage. Their width is taken from their parent element (container), whereas their height depends on their contents. Examples of block level elements are paragraphs and headings. The point about a block level element with being set by its parent element is particularly obvious for the heading, which on a screen that is reasonably wide shows that the box extends all the way from one edge of the browser window to the other. Changing the width of the browser window demonstrates how the height of such elements is set by their content.
- In-line element: these appear in line with other content, hence the name. The default width is set by the contents, not the parent container. As far as I understand it, you cannot set the height or width of an in-line element. However, that doesn't seem to apply to
<img>
elements, even though they are in line — although I guess that does make sense. We can see this type of behaviour with the<em>
example, highlighted with the yellow background.
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):
- Content: Contains the actual displayed contents, for example the text within a paragraph.
- Padding: the space between the contents and the border.
- Border: a border that can be displayed (for example the thin red border round those earlier paragraphs).
- Margin: the space between one box and another.
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
.
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
.
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.