Between curating sites for the HTML5 gallery and answering readers’ questions here at HTML5 Doctor, I see a host of HTML5 sites and their underlying markup. In this post, I’ll show you some of the mistakes and poor markup practices I often see and explain how to avoid them.
Don’t use section as a wrapper for styling
One of the most common problems I see in people’s markup is the arbitrary replacement of
<div>s with HTML5 sectioning elements — specifically, replacing wrapper
<div>s (used for styling) with
<section>s. In XHTML or HTML4, I would see something like this:
<!-- HTML 4-style code --> <div id="wrapper"> <div id="header"> <h1>My super duper page</h1> <!-- Header content --> </div> <div id="main"> <!-- Page content --> </div> <div id="secondary"> <!-- Secondary content --> </div> <div id="footer"> <!-- Footer content --> </div> </div>
Now, I’m instead seeing this:
<!-- Don’t copy this code! It’s wrong! --> <section id="wrapper"> <header> <h1>My super duper page</h1> <!-- Header content --> </header> <section id="main"> <!-- Page content --> </section> <section id="secondary"> <!-- Secondary content --> </section> <footer> <!-- Footer content --> </footer> </section>
Frankly, that’s just wrong:
<section> is not a wrapper. The
<section> element denotes a semantic section of your content to help construct a document outline. It should contain a heading. If you’re looking for a page wrapper element (for any flavour of HTML or XHTML), consider applying styles directly to the
<body> element as described by Kroc Camen. If you still need an additional element for styling, use a
<div>. As Dr Mike explains, div isn’t dead, and if there’s nothing else more appropriate, it’s probably where you really want to apply your CSS.
With that in mind, here’s the correct way to mark up the above example using HTML5 and a couple of ARIA roles. (Note: you may need one
<div> depending on your design.)
<body> <header> <h1>My super duper page</h1> <!-- Header content --> </header> <div role="main"> <!-- Page content --> </div> <aside role="complementary"> <!-- Secondary content --> </aside> <footer> <!-- Footer content --> </footer> </body>
If you’re not quite sure which element to use, then I suggest you refer to our HTML5 sectioning content element flowchart to guide you along your way.
Only use header and hgroup when they’re required
<hgroup> has now been removed from the HTML5 specification, please keep that in mind when reading the rest of this article.
There’s no sense writing markup when you don’t have to, right? Unfortunately, I often see
<hgroup> being used when there’s no need for them. You can get up to speed with our articles on the
<header> element and the
<hgroup> element, but I’ll briefly summarise:
<header>element represents a group of introductory or navigational aids and usually contains the section’s heading
<hgroup>element groups a set of
<h6>elements representing a section’s heading when the heading has multiple levels, such as subheadings, alternative titles, or taglines
Overuse of header
As I’m sure you’re aware, the
<header> element can be used multiple times in a document, which has popularized the following pattern:
<!-- Don’t copy this code! No need for header here --> <article> <header> <h1>My best blog post</h1> </header> <!-- Article content --> </article>
<header> element only contains a single heading element, leave out the
<article> ensures that the heading will be shown in the document outline, and because the
<header> doesn’t contain multiple elements (as the definition describes), why write code when you don’t need to? Simply use this:
<article> <h1>My best blog post</h1> <!-- Article content --> </article>
Incorrect use of
On the subject of headers, I also frequently see incorrect uses of
<hgroup>. You should not use
<hgroup> in conjunction with
- there’s only one child heading, or
<hgroup>would work fine on its own (i.e., without the
The first problem looks like this:
<!-- Don’t copy this code! No need for hgroup here --> <header> <hgroup> <h1>My best blog post</h1> </hgroup> <p>by Rich Clark</p> </header>
In that case, simply remove the
<hgroup> and let the heading run free.
<header> <h1>My best blog post</h1> <p>by Rich Clark</p> </header>
The second problem is another case of including elements when they’re not necessarily required.
<!-- Don’t copy this code! No need for header here --> <header> <hgroup> <h1>My company</h1> <h2>Established 1893</h2> </hgroup> </header>
When the only child of the
<header> is the
<hgroup>, why include the
<header>? If you don’t have additional elements within the
<header> (i.e., siblings of the
<hgroup>), simply remove the
<hgroup> <h1>My company</h1> <h2>Established 1893</h2> </hgroup>
<hgroup> examples and explanations, read the detailed article about it in the archives.
Common mistakes with the figure element
<figure>. The appropriate use of this element, along with its partner-in-crime
<figcaption>, is quite difficult to master. Let’s look at a few common problems I see with
Not every image is a figure
Earlier, I told you not to write extra code when it’s not necessary. This mistake is similar. I’ve seen sites where every image has been marked up as a
<figure>. There’s no need to add extra markup around your images for the sake of it. You’re just creating more work for yourself and not describing your content any more clearly.
The spec describes
<figure> as being
some flow content, optionally with a caption, that is self-contained and is typically referenced as a single unit from the main flow of the document. Therein lies the beauty of
<figure>, that it can be moved away from the primary content — to a sidebar, say — without affecting the document’s flow.
If it’s a purely presentational image and not referenced elsewhere in the document, then it’s definitely not a
<figure>. Other use cases vary, but as a start, ask yourself,
Is this image required to understand the current context? If not, it’s probably not a
<aside>, perhaps). If so, ask yourself,
Could I move this to an appendix? If the answer to both questions is ‘yes’, it’s probably a
Your logo is not a figure
Segueing nicely on, the same applies to your logo. Here are a couple of snippets that I see regularly:
<!-- Don’t copy this code! It’s wrong! --> <header> <h1> <figure> <img src="/img/mylogo.png" alt="My company" class="hide" /> </figure> My company name </h1> </header>
<!-- Don’t copy this code! It’s wrong! --> <header> <figure> <img src="/img/mylogo.png" alt="My company" /> </figure> </header>
There’s nothing else to say here. It’s just plain wrong. We could argue until the cows come home about whether your logo should be in an
<h1>, but that’s not what we’re here for. The real issue is the abuse of the
<figure> should be used only when referenced in a document or surrounding sectioning element. I think it’s fair to say that your logo is rarely going to be referenced in such a way. Quite simply, don’t do it. All you need is this:
<header> <h1>My company name</h1> <!-- More stuff in here --> </header>
Figure can be more than an image
Another common misconception regarding
<figure> is that it can only be used for images. This isn’t the case. A
<figure> could be video, audio, a chart (in SVG, for example), a quote, a table, a block of code, a piece of prose, or any combination of these and much more besides. Don’t limit your
<figure>s to images. Our job as web standards affectionadoes is to accurately describe the content with our markup.
A while back, I wrote about
<figure> in more depth. It’s worth a read if you want more detail or need a refresher.
Don’t include unnecessary type attributes
This is probably the most common problem we see in HTML5 Gallery submissions. While it isn’t really a mistake, I believe it’s best practice to avoid this pattern.
In HTML5, there’s no need to include the
type attribute on
Instead, you can simply write:
<link rel="stylesheet" href="css/styles.css" /> <script src="js/scripts.js"></script>
You can also reduce the amount of code you write to specify your character set, amongst other things. Mark Pilgrim’s chapter on semantics in Dive into HTML5 explains all.
Incorrect use of form attributes
You may be aware that HTML5 has introduced a range of new attributes for forms. We’ll cover them in more detail in the coming months, but in the meantime, I’ll quickly show you a few things not to do.
Several of the new form attributes are boolean, meaning their mere presence in the markup ensures the behaviour is set. These attributes include:
Admittedly, I only rarely see this, but using
required as an example, I’ve seen the following:
<!-- Don’t copy this code! It’s wrong! --> <input type="email" name="email" required="true" /> <!-- Another bad example --> <input type="email" name="email" required="1" />
Ultimately, this causes no harm. The client’s HTML parser sees the
required attribute in the markup, so its function will still be applied. But what if you flip the code on its head and type
<!-- Don’t copy this code! It’s wrong! --> <input type="email" name="email" required="false" />
The parser will still see the
required attribute and implement the behaviour even though you tried to tell it not to. Certainly not what you wanted.
There are three valid ways for a boolean attribute to be applied. (The second and third options only apply if you’re writing XHTML syntax.)
Applying that to our above example, we would write this (in HTML):
<input type="email" name="email" required />
It would be impossible for me to list here all the quirky markup patterns and practices I’ve come across, but these are some of the most frequently seen. What other common markup mistakes have you spotted around the web? Which areas of HTML5 require further clarification? We’d love to help get the wording or examples in the spec changed to make them a little more specific, so leave your thoughts below, and don’t forget to escape your HTML!
Thanks to Ian Devlin, Derek Johnson, Tady Walsh, the HTML5 Gallery curators, and the HTML5 Doctors for their input to this article.