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
There’s no sense writing markup when you don’t have to, right? Unfortunately, I often see <header> and <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:
- The
<header>element represents a group of introductory or navigational aids and usually contains the section’s heading - The
<hgroup>element groups a set of<h1>—<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>
If your <header> element only contains a single heading element, leave out the <header>. 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 <hgroup>
On the subject of headers, I also frequently see incorrect uses of <hgroup>. You should not use <hgroup> in conjunction with <header> when:
- there’s only one child heading, or
- the
<hgroup>would work fine on its own (i.e., without the<header>).
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 <header> altogether.
<hgroup>
<h1>My company</h1>
<h2>Established 1893</h2>
</hgroup>
For more <hgroup> examples and explanations, read the detailed article about it in the archives.
Common mistakes with the figure element
Ah, <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 <figure>.
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 <figure> (an <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 <figure>.
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> element. <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 <script> and <style> elements. While these can be a pain to remove if they’re automatically added by your CMS, there’s really no reason to include them if you’re coding by hand or if you have tight control over your templates. Since all browsers expect scripts to be JavaScript and styles to be CSS, you don’t need this:
<!-- Don’t copy this code! It’s attribute overload! -->
<link type="text/css" rel="stylesheet" href="css/styles.css" />
<script type="text/javascript" src="js/scripts.js"></script>
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.
Boolean attributes
Several of the new form attributes are boolean, meaning their mere presence in the markup ensures the behaviour is set. These attributes include:
- autofocus
- autocomplete
- required
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 required="false"?
<!-- 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.)
requiredrequired=""required="required"
Applying that to our above example, we would write this (in HTML):
<input type="email" name="email" required />
Summary
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.

63 Responses on the article “Avoiding common HTML5 mistakes”
Brilliant article thanks Rich. tag finally I get it!
In the first example why is it and not an article?
Wouldn’t
<input type=”email” name=”email” required>
be just as valid as with the extra ‘/’?
Because html5 is not xhtml, there is no explicit need to (self-)close tags right?
“Earlier, I told you not to write extra code when it’s not necessary”
That’s bad journalism right there. TELLING people what to do because you assume everyone is dumber than you is a sure-fire way to look like an arrogant prick.
I don’t get it with you HTML5 f*cktards. You are just rearranging a few new elements with a big, smug grin on your faces. It’s not exactly brain surgery is it.
If figures can be used for quotes then, would the figcaption be used for the person / reference of the quote?
Would this have been a good example for http://html5doctor.com/blockquote-q-cite/ It seems a bit better than including footers etc in the blockquote. I just find it strange including something that isn’t actually the quote, in the quote.
Interesting article Rich and one that kind of emphasises my fear of creating HTML5 related sites.
With the spec so actively changing and a real in-depth knowledge needed to use any of the new semantic elements – it’s no wonder it makes me, and probably others, incredibly nervous about kick starting HTML5 development :(
It’s so frustrating to see so many ‘HTML5′ sites out there that are blatantly using the semantic structure incorrectly!
“<script href=”js/scripts” /></script>” is correct? Or <script src=”js/scripts.js” /></script> is better?
Just a quick point about the required attribute, if you use the attribute with no value then IE & below won’t recognise it. (ie, you must use at least required=”")
It’s a shame, because I really like that you can just drop these boolean attributes into an element and they’re true because they’re there.
@trolleymusic
Okay, Richard. I take your points, and have been using many of your described habits for awhile. But the more often I read HTML5doctor, the more I am persuaded that it is virtually impossible to write the “perfect” HTML5 website conforming to *all* the recommendations at HTML5doctor versus *all* the recommendations at WHATWG versus the rules so far described at W3.
I will admit, of course, that all these recommendations are matters of *subjective* human interpretation. Yet, HTML5doctor becomes a bit prudish and pedantic at times. The recommendations do *not* always yield code that is more easily maintained, more user-friendly, and more bandwidth friendly!
Seems that the hgroup tag is still being considered for removal:
http://www.whatwg.org/specs/web-apps/current-work/#the-hgroup-element
@Wayne
In IE, would it not just ignore it as it won’t understand that attribute. I’d rely on something like Modernizr at that stage to use an alternative method, with JS for the function and a CSS styling for the visual part of it.
Why exactly do you consider pagination and tertiary navigation not worthy of a <nav> element? Surely they are, by definition, navigation and in the case of pagination, sometimes a very important piece of navigation.
Here is a common mistake made by html5doctor.com. http://jsfiddle.net/trixta/ZMsm7/
Notify your HTML5 stylist to check cross-browser/platform rendering on MacOSX 10.6.8, Chrome 12.0.742.122
Joel asks “Why exactly do you consider pagination and tertiary navigation not worthy of a
I’d consider pagination to be nav (if you really *must* have pagination; why bother?).
You need to ask yourself why you’re marking something up as nav. I do it to help users of assistive technology easily find important navigation, eg site-wide stuff. If you mark up every link that goes somewhere in the site as nav, it’s harder for such users to find the really important stuff.
Thiago Dini asked:
None of them. This is correct:
<script src="js/scripts"></script>Exactly, don’t have close self.
RE: self-closing tags, those aren’t the only typos (link/input)…
Also: don’t blindly use
<aside>for everything that happens to be in a sidebar as per your current design.100% with Ryah and fjpoblam!
It is wrong that . The second and third options are valid even in HTML. See http://www.w3.org/TR/html5/common-microsyntaxes.html#boolean-attributes
@guimihanui: I think Rich meant to write “The second and third options only apply if you’re writing XHTML syntax.”
Thanks to all for your feedback, some specific responses below:
@gnur – you’re right you don’t need the trailing slash but can include it if you prefer to write your markup using XHTML syntax.
@Ric – that’s certainly an option but the context is important. Pullquotes for example wouldn’t be marked up in a figure. Will have a think about that one some more and update the appropriate articles.
@Thiago – Yes that was a typo in the article, it’s now been updated.
@Wayne – Thanks for the tip. Are you referring to IE10? Versions below 10 have no support for HTML5 forms.
@fjpoblam – Interpretation of web standards is nothing new and we will always disagree in some cases. How long did it take us to decide that an unordered list should be used to markup navigation for example? What’s the styling issue you’re seeing? We’ve got the same setup and it’s ok for us.
@Alvin – yes, we wrote an article about that recently. The hgroup hokey cokey
@Joel – It depends on what type of pagination I guess. If we’re talking about Google search results then a nav probably is appropriate. If we’re talking about an article spanning multiple pages to increase ad impressions, not for me. However, as you can see Bruce see’s it from a different angle.
@Christian – I’ve fixed a few typo’s, are there any I’ve not got?
@Mathias – yes good point, thanks for bringing it up. You’re right re ‘syntax’ added that in now!
@Ryah – I thought about not gracing your comment with a response but changed my mind so here goes.
Thankfully, I’m not a journalist. I make websites for a living so no worries there.
I certainly don’t think that everyone is dumber than I am, in fact very much the opposite. A high percentage of our readers pick up errors in our articles and bugs in our code which is invaluable for a resource such as HTML5 Doctor. That’s the beauty of the web community, that we can share information without people always writing nasty, detrimental comments. If you don’t have anything constructive to say, it’s probably best to say nothing at all without going on an unsolicited rant.
I don’t know where to start with your last point. I guess if you don’t like HTML5 and the new elements it has introduced to help make the web a more semantic, accessible place then stick to writing HTML4.
@Ric — I’ve been thinking about
<figure>and<figcaption>for<blockquote>attribution, but there’s one potential problem, the “moved away from that primary content” part. While prints or photos were historically moved to the center of a book, quotations have always been main content. However, I think the common perception of<figure>as a way to just add a caption to an image may render this moot. I also note there’s a poem with citation example in the spec. It’s entirely possible Hixie might agree with you here.“I just find it strange including something that isn’t actually the quote, in the quote.” I’m the opposite here. For me this is like saying the header or footer of an
<article>should be outside it. However you’re definitely not the only one who feels this way.@fjpoblam — “it is virtually impossible to write the ‘perfect’ HTML5 website”. I think you’re approaching this from an XHTML valid/invalid mindset. The HTML5 sectioning elements are very much up to your personal interpretation for example, e.g. the
<nav>discussion above. Rather than worrying, just do the best you can safe in the knowledge that browsers will do their best to render your content, validate, and keep learning. We all make mistakes (my<blockquote>article, anyone? :)), but by discussing them we’re learning and finding better ways to do things. This is great, and for example the<blockquote>spec will probably be changed based on the problem our non-conforming usage uncovered.@Ryah — “It’s not exactly brain surgery is it” Aah, you appear to be after our other medical blog. I trust the content there will be more to your liking ;)
Richard, I think that what gnur meant was either you write:
(pure HTML)
or:
(correct XHTML)
but not:
as you wrote: you mix HTML style with XHTML style. It can be correct for HTML, but unnecessary, and it is not correct XHTML (style).
Good article, anyway. :-)
I don’t see the point in bothering people about adding in type attributes on script and style tags when using examples with XHTML-style closing slashes everywhere (they are just as useless, aren’t they). Except where in the script tags they seem to be closed twice?? I assume that’s a set of typos though.
The confusion over required=”false” maybe comes from sources where I’ve read about the ARIA version: aria-required by itself was true, but if working with JavaScript then aria-required=”false” or aria-required=”" were supposed to turn it off. Or was it?
…by “script tags closed twice”, I mean
<script src=”js/scripts.js” /></script>
The slash after the src.
@all — yup
<script src="js/scripts.js" /></script>was a typo. Thanks for pointing it out, it’s fixed now. For the great HTML vs XHTML closing slashes/talisman debate, check out Dr Bruce’s article HTML 5 + XML = XHTML 5.For the record, in HTML5:<script src=”js/scripts.js”></script>
=
<script src=”js/scripts.js” />
FWIW The styling problem I see is in the bottom divs (if divs is what they are – I didn’t View Source). “RELATED POSTS” overlays advice for posting at the point of “You can also use”. My browser preferences are set at font-size 18. A more adept styling would allow for such a preference (at least it does on my websites).
Oh, and, for my other comment, IMHO, the description of using <i> using an inline class versus using an external stylesheet contributes to a form of “classitis” which I like to avoid.
@Brajeshwar: Agreed, and I do – but if you’re doing a fallback validation, or even just want to get all the required inputs, a
$('input[required]')(to use a jquery example) with<input required/>won’t return anything on <= IE8 —$('input[required=""]')&<input required=""/>will though.@Richard Clark: 8 and below – you can still pick out the elements that have the attribute with 9, even if the attribute has no value associated – and while the browser may have no native support for cool things like validation, having an attribute for required still works from a script point of view.
I really would like to get feedback, about my too short comment above. Mainly, I only shared a link with examples and some explanation. My opinion is, that the following output example is a bad, but common mistake:
<input type="range" oninput=" $( output ).prop( 'value', value ) " />
<output id="output">50</output>
The reason, why I think it is a mistake, has the following reasons. The output element should be implemented as a liveregion, which means everytime, the textcontent changes the changed content is announced by Screenreaders, which is good for a11y, if you are calculating or transforming some input[s], but it is really bad if you simply only repeat the value of an input element. It’s a case of too much accessibility.
Oli Studholme wrote:
The second option can only be used in XHTML5 served as “application/xhtml+xml”. If it is used in ordinary HTML5 (served as “text/html”) the second option is equal to
<script src="js/scripts.js">with no closing tag, and that is obviously invalid, and will probably break badly. The slash has no meaning in plain HTML5!On a side note: The space before the slash in self-closed elements is not needed anymore. The only browser that ever needed it, Netscape (4 and earlier), is long gone. So, if you like the XHTML5 syntax, you can just do this:
<input value="whatever"/><img alt="" src="whatever.png"/>
etc.
@Bertil:
But is it true that Safari is the one browser who does see <script blah blah /> as valid while all others don’t (some “bug” I remember reading about somewhere)? (and if Safari, maybe also Chrome)
developers are still wrong about the use of the HTML5, mainly on issues related to .
Good tips man
For input required, w3c shows it as required=”required” ? http://www.w3schools.com/html5/att_input_required.asp but you just write “input… required”
Is there a difference? I would be inclined to go by the w3c, no?
Lolz, answered my own question: http://dev.w3.org/html5/spec/syntax.html#start-tags
Mmm, I should have read the side bar… Inconvenience of not having a preview facility…
It was:
<input type=”email” name=”email” required>(HTML)<input type=”email” name=”email” required="r"/>(XHTML)not
(half backed…)@Allan: don’t mention W3C with a link to W3Schools! That’s heresy… :-) See W3Fools… ;-)
@fjpoblam — the rendering bug you see will be addressed when we move to a liquid layout. I have no idea what you mean by your “classitis” comment though.
@Bertil Wennergren — thanks for the correction. I must have been thinking of
<link>or something there.@Stomme poes — you’re right. Safari traditionally accepted
<script />due to Dashboard apps. They’ve stopped supporting it now (with Safari 5.1?) as it isn’t compliant with HTML5 (ref: bugs 4071, 10099, 42909).@PhiLho — I pity da W3 foo’! [:mrt:]
Fwiw, “void elements” (and foreign elements = elements from the MathML namespace and the SVG namespace) can have an optional XHTML-style closing slash:
areabasebrcolcommandembedhrimginputkeygenlinkmetaparamsourcetrackwbrRegarding the closing slash, “This character has no effect on void elements, but on foreign elements it marks the start tag as self-closing.”
First up, thanks for the great article. You’ve got a fantastic resource here for html5 markup.
One thing I wanted to clarify was the
<header>element. I can certainly understand the reasoning behind not including extra markup when you don’t need to, as in your example of leaving out the<header>element if there’s only a single<h1>. Reading through the W3c Spec though, it states:Specifically, it says “an h1-h6 element”. Element being singular. So, would it really be that bad if you enclose a single h1 within a header?
very useful article thanks for sharing.
Didn’t you know that HTML 5 isn’t about semantic markup? It was created to give “front-end developers” some specialized knowledge to justify their job titles ;)
How come ‘Pagination controls’ are deemed unworthy of nav tags?
I know they’re of lesser importance than your main site navigation but all the same they may hold significant weight within their context
I disagree with leaving off the type attributes for scripts and style sheets. Sure, HTML5 doesn’t need them. But….
You’re site is still going to be hit by HTML4 browsers and they do need them..
No they don’t. Small changes like this would have never been accepted in HTML5 if they broke backwards compatibility.
“There’s no sense writing markup when you don’t have to, right?”
I guess that’s a matter of preference (or even a dogmatic difference) that wouldn’t qualify it as a mistake. If you wish to plan for the future or if you consider the html structure of a component to be a generic semantic and structural description that should be able to expand over time and across different sites, then yeah, there is sense in writing mark-up that might be too verbose in one particular example on one particular page of your site.
Thanks about the advice. I’d always figured that the element had more use than for just images. Tables, video, canvas(?!), etc, etc. Go figure!
I have translated this great article into chinese, If you like chinese version you can vist 如何避免 HTML5 的常见误区 Thanks Richard Clark
The best article of html5doctor.
Thanks for sharing!
Regarding images and image galleries, what would be the most proper way to display a set of images and captions on a page if those images are the primary content? Definitely not
<aside>(I’m fairly sure), but I’m having trouble understanding if<figure>and<figcaption>would be the proper tags to use.My intended use case is grouping 1-3 pictures within a
<figure>and using<figcaption>to label the group as a whole.Thanks for the excellent article and thanks in advance for any follow-up/help/advice.
Very usefull article. I realize there’re many things to improve when I designing my websites, so thanks for sharing your experience.
Brilliant and helpful article for an HTML5 beginner, thanks muchly :)
Excellent article.
Tky
navbugs me. It should be context-sensitive. If it’s a descendant of anarticleor asectionit’s primary navigation for that context. If it’s a descendant ofbody(possibly withheaderor somedivs between) it’s primary navigation for the site.But that’s not the way the spec reads, so I guess I’ll just have to either get used to doing something that feels weird & wrong…
@Usme Cah — while the spec doesn’t state this explicitly in
<nav>’s description, your explanation is dead on. Refer to the spec on other sectioning elements like<article>. Also note the spec’s examples for<nav>are both context-sensitive. Yay for being right eh? :)Great article :)
HTML5 is awesome & these mistakes occur many times unintentionally..
What a brilliant article. I’m currently working on a few html5 sites and this was a very enlightening read for me. Cheers.
Just a note – your link to Mark Pilgrim’s Dive Into HTML5 semantics page points to a 410. I found it eventually at .info rather than .org.
http://diveintohtml5.info/semantics.html
@Jack Westbrook — d’oh! We’re aware of the problem (ahem) but actually updating links seems to have slipped through the cracks… until now! Thanks for the prompt :)
Very good article, thanks indeed the new semantic gives a new standard how we define a html. But still confuse who benefits all this new semantic ? Is there a javascript library that handle this specialy ? Sorry if my question is look silly.
@Richard Clark — “I’ve fixed a few typo’s, are there any I’ve not got?”
You made a typo in the word “typo’s” (should be “typos”).
I know you said you’re not a journalist, but you’re a smart guy!
This was a joke, right? Please?
Great article, no offense intended! :D
Thanks for the article. How does one style multiple instances of footer on a page without confusing the browser ?
Join the discussion.