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
In our header,
we use it for marking up the blog title & subtitle so that
the subtitle doesn't appear in the document
outline.
h1
–h6
elements when the heading has multiple levels, such as
subheadings, alternative titles, or taglines.
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
(emphasis mine). Each of our sidebar's sections has a heading
and should explicitly appear in the outline, so we use
section
element is appropriate only if the element's contents would
be listed explicitly in the document's outline<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[.…] Anarticle
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 thediv
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 innerarticle
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 asarticle
elements nested within thearticle
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>