Theresa O’Connor

Blog templates: a case study in using HTML5’s sectioning elements

The HTML5 spec introduces several new sectioning elements to HTML: <article>, <section>, <header> & <footer>, <nav>, <aside>, and <hgroup>. There’s widespread confusion about when to use these elements. I’d like to write a little bit about these elements and how to use them appropriately, using blog template markup as a motivating example.

Base page template

Let's dive right in, starting with a blog's base page template. This should include the site's header, footer, and sidebar, but doesn't include the "meat," which will be provided by relevant sub-templates.

<!DOCTYPE html>
<html lang="en-US-x-Hixie">
  <head>
    <title>My Blog: Adventures in cat pictures</title>
  </head>
  <body>
    <header> <!-- site header -->
      <hgroup> <!-- squashes subtitle in doc outline -->
        <h1>My Blog</h1>
        <h2>Adventures in cat pictures</h2>
      </hgroup>
      <nav> <!-- main blog navigation links -->
        <ul>
          <li><a href="…">Front page</a></li>
          <li><a href="…">About My Blog</a></li>
          … other navigation links …
        </ul>
      </nav>
    </header>

    … main content goes here …

    <aside> <!-- sidebar -->
      <section>
        <h1>Search My Blog</h1>
        <form action="…">
          <input name="q" type="search"
          placeholder="To search, type and hit enter" />
        </form>
      </section>
      <section>
        <h1>Blogroll</h1>
        <ul>
          <li><a href="…">My other blog</a></li>
          <li><a href="…">Your blog</a></li>
          <li><a href="…">Your friend’s blog</a></li>
        </ul>
      </section>
    </aside>
    <footer> <!-- site footer -->
      <p>Copyright © 2009 You. All rights reserved.</p>
      <address>
        <a href="mailto:you@example.org">you@example.org</a>
      </address>
    </footer>
  </body>
</html>

That's a lot of markup to digest at once, so let's break that down one piece at a time. First, consider the page header:

<header> <!-- site header -->
  <hgroup> <!-- squashes subtitle in doc outline -->
    <h1>My Blog</h1>
    <h2>Adventures in cat pictures</h2>
  </hgroup>
  <nav> <!-- main blog navigation links -->
    <ul>
      <li><a href="…">Front page</a></li>
      <li><a href="…">About My Blog</a></li>
      … other navigation links …
    </ul>
  </nav>
</header>

The site header uses three new elements: <header>, <hgroup>, and <nav>.

The <header> element can be used as a header of any sectioning element. In this case, it's being used as the header of <body>, which is just as much a sectioning element as the new ones like <article>. For styling purposes, authors may wish to distinguish between a site-wide heading and page- or section-specific headings. This is possible with a child selector like body>header (or via class="" & id="" for browsers that don't support such selectors).

The <hgroup> element is used to group a set of h1h6 elements when the heading has multiple levels, such as subheadings, alternative titles, or taglines. In our header, we use it for marking up the blog title & subtitle so that the subtitle doesn't appear in the document outline.

The spec defines <nav> as representing a section of a page that links to other pages or to parts within the page: a section with navigation links. As a sectioning element, <nav> can have its own header. In this case there's no need for one.

Next, take a look at the sidebar:

<aside> <!-- blog sidebar -->
  <section>
    <h1>Search My Blog</h1>
    <form action="…">
      <input name="q" type="search"
             placeholder="To search, type and hit enter" />
    </form>
  </section>
  <section>
    <h1>Blogroll</h1>
    <ul>
      <li><a href="…">My other blog</a></li>
      <li><a href="…">Your blog</a></li>
      <li><a href="…">your friend’s blog</a></li>
    </ul>
  </section>
</aside>

The sidebar utilizes several new elements and attributes: <aside>, <section>, <input type="search">, and the placeholder attribute.

The sidebar itself is represented with an <aside> element, because it consists of content that is tangentially related to the main content of the page.

Each section of the sidebar is contained in a <section> element. HTML5 defines <section> to be a generic document or application section. A section, in this context, is a thematic grouping of content, typically with a heading, possibly with a footer.

Essentially, a <section> is a portion of a larger work which participates in the larger work's outline. The spec says that the section element is appropriate only if the element's contents would be listed explicitly in the document's outline (emphasis mine). Each of our sidebar's sections has a heading and should explicitly appear in the outline, so we use <section> for them.

You may have noticed that—with the exception of the blog subtitle—I've only been using <h1> elements for headings, and not <h2> through <h6>. This is because sectioning elements scope heading elements, so that this document:

<body>
  <h1>Heading 1</h1>
  <h2>Heading 1.1</h2>
  <h3>Heading 1.1.1</h3>
  <h2>Heading 1.2</h2>
</body>

and this document:

<body>
  <h1>Heading 1</h1>
  <section>
    <h1>Heading 1.1</h1>
    <section>
      <h1>Heading 1.1.1</h1>
    </section>
  </section>
  <section>
    <h1>Heading 1.2</h1>
  </section>
</body>

have the same outline. Future UAs are expected to render section>h1 smaller than body>h1. For now, though, you could continue to use <h1><h6>, even with the new sectioning elements, because the child heading element with the highest rank is considered the heading of the section.

The search form uses some HTML5 bits and pieces that aren't strictly speaking on-topic for this article, but I'll go ahead and explain them anyway. Search boxes (<input type="search">) behave like text boxes (type="text"), but may have a different appearance. They've been implemented in WebKit (Safari) for several years, and were adopted by HTML5 from there. The placeholder attribute provides as native HTML functionality something many web developers hack together with JavaScript. Placeholder text is displayed inside the input field as long as the field is empty and not focused. As soon you click on (or tab to) the input field, the placeholder text disappears. (Dive Into HTML5)

Finally, the footer:

<footer> <!-- site footer -->
  <p>Copyright © 2009 You. All rights reserved.</p>
  <address>
    <a href="mailto:you@example.org">you@example.org</a>
  </address>
</footer>

There's not much to say about this footer: it contains site-wide metadata like rights information, contact information, and the like. Suppose instead you'd like a Powazek-style fat footer. Sounds great! As of spec rev 3751, you can go right ahead and do that. Here's a fat footer cobbled together from my example header, sidebar, and footer:

<footer> <!-- site footer -->
  <nav> <!-- main blog navigation links -->
    <h1>Navigation</h1>
    <ul>
      <li><a href="…">Front page</a></li>
      <li><a href="…">About My Blog</a></li>
      … other navigation links …
    </ul>
  </nav>
  <section>
    <h1>Blogroll</h1>
    <ul>
      <li><a href="…">My other blog</a></li>
      <li><a href="…">Your blog</a></li>
      <li><a href="…">your friend’s blog</a></li>
    </ul>
  </section>
  <section>
    <h1>Rights</h1>
    <p>Copyright © 2009 You. All rights reserved.</p>
    <address>
      You <a href="mailto:you@example.org">you@example.org</a>
    </address>
  </section>
</footer>

Individual blog posts

Now it's time to talk about what we put where I have that … main content goes here … placeholder above. There are two cases I'd like to look at: pages that hold only one blog post, and archive pages which hold several at once. Let's start with the individual blog post template first.

<article>
  <header> <!-- blog post header -->
    <h1>My Blog Post</h1>
    <p>
      posted by You at <time
      datetime="2009-09-04T16:13:40-07:00" pubdate>1:40 PM
      on September 4th, 2009</time>
    </p>
  </header>
    … body of blog post …
  <footer> <!-- blog post footer -->
    <p>Comments are closed at this time.</p>
  </footer>
</article>

In addition to some elements we've already covered, this markup uses <article>, <time>, and <time>'s pubdate attribute. (I'm going to skip explaining <time> and pubdate="" as they're tangential to the points I'm aiming to make here.)

It's pretty obvious (and uncontroversial) that <article> is the best sectioning element to use for a blog post.

The article element represents a section of a page that consists of a composition that forms an independent part of a document, page, application, or site[.…] An article element is "independent" in the sense that its contents could stand alone, for example in syndication, or as a interchangeable component on a user-configurable portal page.

Now, suppose your blog post is very long and has several distinct pieces with their own subheadings. Unsurprisingly, this is a case for the <section> element:

<article>
  <header>…</header>
  <section>
    <h1>Part the first</h1>
    … first part of blog post …
  </section>
  <section>
    <h1>Part the second</h1>
    … second part of blog post …
  </section>
  … more sections …
  <footer>…</footer>
</article>

In both of the above cases, there's no element that contains just the "meat" of the blog post. The <article> contains the meat, but also the header and footer. The <section>s just contain one subsection each. Perhaps you need a "meat" element, for styling purposes or some such. The correct element to use for this is <div>. Here's what the spec has to say about this case (emphasis mine):

The section element is not a generic container element. When an element is needed for styling purposes or as a convenience for scripting, authors are encouraged to use the div element instead.

Using <div> for such a situation looks like this in the case of a short blog post:

<article>
  <header>…</header>
  <div>
    … body of blog post …
  </div>
  <footer>…</footer>
</article>

And like this for a longer one:

<article>
  <header>…</header>
  <div>
    <section>
      <h1>Part the first</h1>
      … first part of blog post …
    </section>
    <section>
      <h1>Part the second</h1>
      … second part of blog post …
    </section>
    … more sections …
  </div>
  <footer>…</footer>
</article>

Comments

The spec says to use nested <article> elements for comments:

When article elements are nested, the inner article elements represent articles that are in principle related to the contents of the outer article. For instance, a Web log entry on a site that accepts user-submitted comments could represent the comments as article elements nested within the article element for the Web log entry.

<article>
  … header and such …
  … body of blog post …
  <article> <!-- comment 1 -->
    … body of comment …
    <footer> <!-- comment footer -->
    … who wrote the comment, etc. …
    </footer>
  </article>
  … more comments …
  … blog post footer …
</article>

But what about the "add a comment" form? They typically appear after any existing comments. I'm itching for a container to hold both the comments and the form, and I think the best match is <section>. After all, I think it's appropriate for the comments section to participate in the document outline.

<article>
  … header and such …
  … body of blog post …
  <section>
    <h1>Comments</h1>
    <article> <!-- comment 1 -->
      …
    </article>
    … more comments …
    <form> <!-- add comment form -->
      …
    </form>
  </section>
  … blog post footer …
</article>

Archive pages

Archive pages typically have multiple blog posts on them. So the most obvious way to mark such a page up would be to put the <article> elements, one after another, where I have that … main content goes here … placeholder above.

<body>
  <header>…</header>
  <article>… blog post 1 …</article>
  <article>… blog post 2 …</article>
  … more blog posts …
  <aside>…</aside>
  <footer>…</footer>
</body>

Now, just as in the case of marking up blog post "meat" above, you might want an element which contains all of the blog posts. And as before, the correct element to use for this is <div>.

<body>
  <header>…</header>
  <div>
    <article>… blog post 1 …</article>
    <article>… blog post 2 …</article>
    … more blog posts …
  </div>
  <aside>…</aside>
  <footer>…</footer>
</body>