Ian Marshall

Getting Started with HTML and CSS

Lesson 5: Containers and Semantics

No doubt you've noticed that the navigation at the top of this page stays unaltered while you click from page to page. The content below it changes, of course, which is expected. But the "look and feel" of the page, including the top navigation, stays consistent. This is because I've set a default style to all of my page headers.

What's a header? And how do you style it? Well, here's an example:

No images. Just CSS. In your browser, the above code looks like this:


  1. The details of new CSS rules like repeating-linear-gradient, border-radius, and text-shadow will be saved for a more advanced course. (But that doesn't mean you cannot tinker with them on your own!)

Okay, a lot to talk about here. First, all the styling is for the <header> element only, not for any of its contents. Some of the CSS rules affect the <header> itself (like background) while others are passed along to its text elements, <h1> and <p> (like color).

The <header> is a container of other HTML elements. That's its only job, to hold HTML in a particular semantic group, although it can itself be styled with CSS. A header could be at the top of a page, or at the top of a column, or at the top of a sidebar, etc. It has a semantic partner in <footer>, which as you can imagine tends to be at the bottom. In between, the page may have a <main> element to represent, well, the main page content.

Here's a web page comprising three empty containers.

What goes in each of these containers? That's up to you, of course, and is dependent on the page content you're working with. Not every page needs a <header> or <footer>, although using a single <main> isn't a bad idea for accessibility reasons. (We'll discuss accessibility in a more advanced course.)


Imagine a web page with only one possible container. Let's call it a <div>, as in a page division. Absolutely anything that could be accomplished using <header>, <main>, and <footer> can also be accomplished using <div>. However, it would look like this:

Which <div> has the most important content?

Who knows?

Unfortunately, it would take a human being reading the comments to figure out how the content of each division relates to the page as a whole. Well, maybe even without comments, humans might be able to figure it out. But machines cannot. To a screen reader, a browser that reads aloud the page content for, often, blind users, each <div> has exactly the same importance as the others. Footer content would be read with the same emphasis as header content. That's not doing the content justice. Nor blind users. What other machines need to read the HTML? How about web crawlers, like those for Google, that determine just how to rank your page in search results? If you're at all interested in search engine optimization (SEO), then you'll use semantic containers instead of a single, generic, all-purpose one.

I bring this up because prior to HTML5, there were only <div> container elements available. The fifth version of HTML was released in 2014 and, among many other great improvements, introduced a slew of new semantic container elements that should be used before even considering a <div>.

<article>independent, self-contained content that could be distributed or published separately
<aside>dependent content removed from the main content such as a side bar
<figcaption>caption, usually text, for a figure
<figure>a container for a diagram, illustration, or other content needing a caption
<footer>supplementary content after the main content
<header>introductory content before the main content
<main>one container for the page's main content
<nav>container for navigation elements such as links
<section>dependent, but thematic grouping of content, usually with a headline

Nested Containers

Yes, it is possible to have containers inside other containers—with one restriction. The <main> element should be nested directly in the <body> and there should be only one of them in the entire HTML document. What happens if you break this rule? Nothing! But your HTML will not validate.

Other than that, you can mix things around as you see fit, and as the content semantics require. For example, an <article> may very well have both a <header> and a <footer>. An <aside> may have a <nav>. A <figure> may have more than one <figcaption>, and an image-gallery <section> may have many <figure> elements.

Exercise 5.01: Page Containers


Using your code editor, create a new document called page_containers.html. Type the code below into that document, matching my syntax and line numbers, and check your work in a browser.




  1. The <body> color fills the screen, even if the content doesn't.
  2. There are a lot of strange color names. (Yes, there are!)


  1. Switch the positions of the <header> and <footer>.

Warning: Lots of Typing Ahead!

Pretty much from here on out, the examples will be much longer and involve more typing. Gee, I hope you've been keeping up with your typing skills! Make use of your HTML template; that part needn't be retyped every time. And, for some text, especially long URLs, I'll of course allow you to cut and paste. But for the rest, do try to stay committed to typing. You're working on more than one critical skill here.

Exercise 5.02: Marion County


Using your code editor, create a new document called marion_county.html. Type the code below into that document, matching my syntax and line numbers, and check your work in a browser.




  1. The CSS for <header> affects both of them, even though they're nested differently: the first is in the <body> and the second is in the <main>.
  2. margin seems to separate elements.
  3. padding seems to make elements bigger.
  4. The headlines (<h1>, <h2>, <h3>) keep getting smaller as they appear later in the document.


  1. CSS rules will apply to anything in the selector, or the part before the curly braces. If a rule set has a header as its selector, then each <header> in the HTML will apply the custom styling, no matter where they appear in the HTML.
  2. margin is the "keep away from me" styling rule, meaning that its value is the minimum allowable space between itself and any other element. padding adds extra space on the inside of an element; it's the distance between an element's content and where its border would appear. We'll discuss this in more depth in a later lesson.
  3. Headlines from <h1> to <h6> represent a semantic order of importance on the entire page, regardless of position, nesting, or styling. A machine reader should have access to the most important content on the page (<h1>) and compare it to relatively lesser content elsewhere. If, for example, you were to pull out only the headlines for an entire page, they should make semantic sense in their order of importance.


  1. Weird things happen if you remove either border-top or border-bottom from the header. (This is default behavior for CSS, which we'll explore more deeply in a later lesson.)

Exercise 5.03: Astrology


Using your code editor, create a new document called astrology.html. Type the code below into that document, matching my syntax and line numbers, and check your work in a browser.




  1. What's display: inline-block; in the CSS?
  2. Line 8 seems to have a complex selector, header, main.
  3. Line 10 seems to have a complex selector, figure h2.


  1. When a CSS selector comprises two or more tag names separated by a comma, then the rule affects all elements listed. The comma acts as an "and" in the selector.
  2. When a CSS selector comprises two or more tag names separated by a space, then the rule affects only the last element as long as it's nested in the previous element. In other words, the font-size: 4em; will affect only <h2> elements nested inside a <figure>.


  1. Try removing the display: inline-block; and find out what happens! Write down your observations. (We'll discuss display more deeply in another lesson.)
  2. Change the <h1> on line 15 to an <h2>. Is the font size 4em? Why or why not?

Exercise 5.04: Pet Adoption


Using your code editor, create a new document called pet_adoption.html. Type the code below into that document, matching my syntax and line numbers, and check your work in a browser.




  1. Clicking any of the buttons doesn't do anything.
  2. All of the CSS selectors begin with header.


  1. The <button> element isn't actually intended to work quite in this way. It's usually paired with a form, or has some JavaScript that works with it. On its own, it does nothing but provide an example of what a navigation might look like, even if the links are not currently functional.
  2. For this document, the CSS selectors are over qualified, meaning there's unnecessary detail to the selectors. For example, there are only one set of buttons on the page, so a selector of button would work well enough. Using header nav button is way over qualified. However, as your HTML and CSS documents get longer with more and more content, you may be glad to see the word header before each rule that affects anything within the <header>. You'll develop your own preferences the more you work, just as I did—and continue to do.


  1. Change the margins.

Exercise 5.05: Hook & Ladder


Using your code editor, create a new document called hook_and_ladder.html. Type the code below into that document, matching my syntax and line numbers, and check your work in a browser.


Image free from Wikimedia


  1. Using display: inline-block; seems to put elements side by side instead of one above the other.
  2. the width: 90%; for the buttons seem to be relative to the element the buttons are nested in.


  1. The CSS display and vertical-align deserve their own lesson, which we'll tackle later. As usual, though, feel free to tinker with it!


  1. When you use a percentage for CSS width, the browser needs to calculate an actual pixel width as that percentage of something. So it looks at what the element is nested in, and then the element that's nested in, etc., to find an element that has an actual pixel width. In the case of the above, the <button> has a width of 90% of…what? It's in a <nav>, which has no explicit pixel width. But that <nav> is in an <aside> that does have an explicit pixel width of 150px. So each <button> will have a width of 90% of 150 pixels, or 135 pixels.


  1. What happens if you remove vertical-align: top; from the CSS?
  2. What happens if you switch the entire <main> (lines 49–64) with the entire <aside> (lines 65–73)?


When HTML content starts to get complex, it's helpful to use semantic containers like <article> and <header> to group related HTML. This provides both human and machine readability, even with long, deeply nested content. It also becomes easier to style entire pages by styling the large container blocks first, then applying detailed styling to individual elements only as needed.

A couple of important notes:

  1. There should be only one <main> container on any single HTML page.
  2. The headlines (<h1> through <h6>) are relative to each other no matter where they appear on the page.