Divs are played out
We all love our <div> tags. They've been around for decades, and for decades they've been the go-to element when you need to wrap some stuff in a block for styling or structural purposes. It's still very common to look through production websites and see stuff like this:
<div class="container" id="header">
<div class="header header-main">Super duper best blog ever</div>
<div class="site-navigation">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/archive">Archive</a>
</div>
</div>
<div class="container" id="main">
<div class="article-header-level-1">
Why you should buy more cheeses than you currently do
</div>
<div class="article-content">
<div class="article-section">
<div class="article-header-level-2">
Part 1: Variety is spicy
</div>
<!-- cheesy content -->
</div>
<div class="article-section">
<div class="article-header-level-2">
Part 2: Cows are great
</div>
<!-- more cheesy content -->
</div>
</div>
</div>
<div class="container" id="footer">
Contact us!
<div class="contact-info">
<p class="email">
<a href="mailto:us@example.com">us@example.com</a>
</p>
<div class="street-address">
<p>123 Main St., Suite 404</p>
<p>Yourtown, AK, 12345</p>
<p>United States of America</p>
</div>
</div>
</div>
Hoo, that's a lot of <div>s. And hey, it works. I mean, mostly. It has the structure you need, and I'm sure it'll look the way you intend by the time you're done styling it. But it has some big problems:
Accessibility - Many a11y tools are pretty smart, and try their best to parse the structure of a page to help guide users through it in the way the page's author intends, and to give users easy jump points to navigate quickly to the section of the page they care about. But
<div>s don't really impart any useful info about the structure of a document. The smartest a11y tool in the world still isn't a human, and can't be expected to parseclassandidattributes and recognize all the weird and wild ways that devs all over the world name their blocks. I can recognize thatclass="article-header-level-2"is a subheading, but a robot can't. (And if it can, get it out of my computer, I'm not ready for the AGI revolution just yet.)Readability - To read this code, you need to carefully scan for the class names, picking them out from between the
<div class="..."></div>boilerplate. And once you're a few levels deep in the markup, it becomes tricky to keep track of which</div>closing tags go with which<div...>opening tags. You start to rely very heavily on IDE features like coloring different indentation levels or highlighting the matching tag for you to keep track of where you are, and in larger documents it can require a lot of scrolling on top of those features.Consistency and standards - It can be frustrating to start a new job or move to a new project and have to learn from scratch all the crazy markup conventions used across the codebase. If everyone had a standardized way to mark up common structures in web documents, it would be much easier to skim an HTML file in an unfamiliar codebase and get a quick handle on what it's supposed to represent. If only there was such a standard...
HTML5: Such a standard
HTML5 is not new. That's an understatement; an initial working draft was released for public comment in January of 2008 (11 years ago!), and it became a full-fledged W3C recommendation in October of 2014, 4½ years ago. So, like, it's been around for a while.
One of the primary advancements of HTML5 was introducing a standardized set of semantic elements. The term "semantic" refers to the meaning of a word or a thing, so "semantic elements" are elements designed to mark up the structure of a document in a more meaningful way, a way that makes it clear what they're for, what purpose they serve in the document. And importantly, since they're standardized, these elements define the document in a way that everyone can use and understand, robots included.
I think the HTML5 spec itself sums up the issue nicely in a note under the definition of the <div> element:
NOTE:
Authors are strongly encouraged to view the div element as an element of last resort, for when no other element is suitable. Use of more appropriate elements instead of the div element leads to better accessibility for readers and easier maintainability for authors.
— https://www.w3.org/TR/html5/grouping-content.html#the-div-element
I'll divide the semantic block elements into two categories: primary structure and content indicators. These aren't standard terms or anything; I just made them up for this article. But I think the distinction is useful enough. 🤷♂️
Primary Structures
There's a super common pattern that can be found in websites, tutorials, and even CSS libraries all over the internet, and for good reason. We often divide a page at its topmost level into three regions: header, main, and footer, then divide those regions into sections as needed. I included this in my example above to prove the point:
<div class="container" id="header">...</div>
<div class="container" id="main">
...
<div class="article-section">...</div>
...
</div>
<div class="container" id="footer">...</div>
I've seen (and used) this pattern for decades, and it makes a ton of sense to structure a document this way, both for readability of the HTML and for easier styling of the page in CSS. The header and footer elements also make partial templates in languages like PHP or Rails/ERB a ton easier to work with, as you can include common header and footer partials all over the site:
<?php include 'header.php'; ?>
<div id="main">...</div>
<?php include 'footer.php'; ?>
So here's the thing: everyone agrees that this is a nice pattern to follow. And that includes the folks at the WHATWG and W3C, who standardized the pattern into four new elements in HTML5 with very clear names: <header>, <main>, <footer>, and <section>.
Bookends: <header> and <footer>
The <header> and <footer> elements are basically twins: they're very similarly defined in the spec and follow the same set of rules about where they're allowed to be used, with the only difference being their semantic purposes: headers go at the beginnings of things, footers go at the ends of things. And by "things", I mean more than just the <body> of your page: this pair of elements are designed to be used within any part of your document that represents a chunk of content with a clear beginning and end. This can include things like forms, articles, sections of articles, posts on a social media site, cards, etc.
Headers and footers are attached semantically to the closest "sectioning root" or "sectioning content" element. These are things like <body>, <blockquote>, <section>, <td>, <aside>, and lots of others; click the links above if you want the full lists. Assistive technologies can use these elements and others to generate an outline of a document, which can help users navigate it more easily. You shouldn't have more than one <header> or <footer> per sectioning root/content. (One of each is fine, but not two of the same.)
As a final note, <header>s very often hold the heading element (<h1>-<h6>) for their context. This is not necessary, but can help to group other related elements with the heading, like links, images, or subheadings, and can help maintain a consistent structure even when the heading is the only element in the <header>.
The good stuff: <main>
The third primary region element, <main>, is special. The spec says two very important things about <main>:
The main content area of a document includes content that is unique to that document and excludes content that is repeated across a set of documents such as site navigation links, copyright information, site logos and banners and search forms (unless the document or application’s main function is that of a search form).
— https://www.w3.org/TR/html5/grouping-content.html#elementdef-main
So <main> is where you put the good stuff, the important parts of a page, the reason the user came to this page in particular, not your site in general. In other words, the main content. 😯😲🤯
All that other stuff, logos and search forms and navigation and such, can go in a <header> or <footer> within the <body> but outside of <main>.
There must not be more than one visible main element in a document. If more than one main element is present in a document, all other instances must be hidden using the hidden attribute.
— https://www.w3.org/TR/html5/grouping-content.html#elementdef-main
This is pretty unique. Unlike <header> and <footer> (and most other block elements), <main> can't be used all over the page within arbitrary sectioning content; it should be used once and only once. Or rather, it can be used multiple times in a document, but only one <main> element should be visible at a time; all others must be hidden with the hidden attribute, which basically acts like display: none; in CSS. If you think about it, this suggests a pretty useful pattern for preloading views in an app: create a new <main hidden>, fetch some content that the user is likely to view next (e.g., the next article in a series, the next slide in a slideshow, etc.), and when the user clicks the link/button to load that view, swap out the current <main> with the preloaded one by toggling the hidden attribute on both.
Before continuing, let's pause and review the example from above. Here's how it would look if we used <header>, <main>, and <footer> for the main structure of the article:
<header>
<h1>Super duper best blog ever</h1>
...
</header>
<main>
<h2>Why you should buy more cheeses than you currently do</h2>
...
</main>
<footer>
Contact us!
<div class="contact-info">this.is.us@example.com</div>
</footer>
That's so much nicer already! But there's still plenty of work to do.
Break it down: <section>
So we've got a basic outline for our page: a header, a footer, and a main content region. Now it's time to add some of that sweet, sweet content.
Typically you'll want to break your content down into sections, especially for mass text content like this article, because no one likes reading impenetrable walls of text.
That's where <section> comes in. This one is the simplest in terms of rules: structurally speaking, it's basically just a <div> with special semantic meaning. A <section> begins a new "sectioning content" region, so it can have its own <header> and/or <footer>.
What's the difference, then, between a <section> and a regular old <div>, and when should you use each? Well, allow me to quote the spec once again:
NOTE:
The<section>element is not a generic container element. When an element is needed only for styling purposes or as a convenience for scripting, authors are encouraged to use the<div>element instead. A general rule is that the<section>element is appropriate only if the element’s contents would be listed explicitly in the document’s outline.
— https://www.w3.org/TR/html5/sections.html#the-section-element
You know, as a quick aside, the HTML5 spec is actually pretty readable. It's one of the more readable specs out there. Every time I glance at it for a quick answer, I inevitably learn something unexpected and useful, especially if I start clicking links. Give it a try some time!
So in short, if you would list this portion of the document in the table of contents, use a <section>. If not, use a <div> or something else.
Content Indicators
Okay, so we've got a solid structure for our page. Instead of just slinging <div>s all over, we've explicitly marked the main content region of the page, and we've called out headers, footers, and sections. But there's definitely more semantics than that to our document.
Let's talk about a few of the elements added in HTML5 that communicate content semantics rather than structure.
The whole shebang: <article>
The <article> element is used to represent a fully self-contained region of content, something that could be plucked out of your page and dropped into another and still make sense on its own. This might be a literal article or blog post, but could also be used for a social media post like a tweet or a Facebook wall post.
The HTML5 spec recommends that articles always have a heading that identifies what it is, ideally using a heading element (<h1>-<h6>). An <article> can also have <header>, <footer>, and <section> elements, so you really could use it to embed a full document fragment with all the structure it needs within another page.
To return to the example from the way up above, let's rewrite the class="article-*" elements using an <article> and some of the other elements we've discussed.
<article>
<header>
<h1>Why you should buy more cheeses than you currently do</h1>
</header>
<section>
<header>
<h2>Part 1: Variety is spicy</h2>
</header>
<!-- cheesy content -->
</section>
<section>
<header>
<h2>Part 2: Cows are great</h2>
</header>
<!-- more cheesy content -->
</section>
</article>
Isn't that a ton more readable than the original? And again, not only is it easier to read, it's way more useful for assistive tech; robots can't always figure out your specific class name pattern, but they can follow this structure.
Getting around: <nav>
This element is a bit more well-known than others. <nav> is designed to clearly identify the main navigation blocks on the page, the groups of links that help the user find their way around the rest of the site (e.g. a site map or list of links in the header) or the current page (e.g. a table of contents).
In our example up top, let's apply a <nav> to that group of links in the header.
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/archive">Archive</a>
</nav>
Doesn't change the structure at all, but you know what it is at a glance rather than needing to read and process the class name on a <div> to figure it out, and more importantly the robots can find it too.
Getting in touch: <address>
The last element we'll discuss is <address>. This element is intended to call out contact info, and it's often used in the main page <footer> to markup the mailing address, phone number, customer service email address, etc. for a business.
Interestingly, the rules for how to markup the content within an <address> element is left open. The spec mentions that there are several other specs that address this, and it probably is outside the scope of HTML itself to provide that level of granularity.
A common solution is RDFa, also a W3C spec, which uses attributes on tags to label the different components of data. Here's what the footer from our example might look when marked up with <address> elements and RDFa:
<footer>
<section class="contact" vocab="http://schema.org/" typeof="LocalBusiness">
<h2>Contact us!</h2>
<address property="email">
<a href="mailto:us@example.com">us@example.com</a>
</address>
<address property="address" typeof="PostalAddress">
<p property="streetAddress">123 Main St., Suite 404</p>
<p>
<span property="addressLocality">Yourtown</span>,
<span property="addressRegion">AK</span>,
<span property="postalCode">12345</span>
</p>
<p property="addressCountry">United States of America</p>
</address>
</section>
</footer>
RDFa is admittedly a bit verbose, but it's pretty handy for marking up data. If you're interested in learning more about RDFa, here's a few links:
- The W3C's RDFa primer
- A description of schemas and links to a bunch of them on schema.org
- The
LocalBusinessschema used above
Conclusion
Okay, we've covered a lot, and we've seen a lot of it applied to our example in bits and pieces. But let's put it all together and see what it looks like.
<header>
<h1>Super duper best blog ever</h1>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/archive">Archive</a>
</nav>
</header>
<main>
<article>
<header>
<h1>Why you should buy more cheeses than you currently do</h1>
</header>
<section>
<header>
<h2>Part 1: Variety is spicy</h2>
</header>
<!-- cheesy content -->
</section>
<section>
<header>
<h2>Part 2: Cows are great</h2>
</header>
<!-- more cheesy content -->
</section>
</article>
</main>
<footer>
<section class="contact" vocab="http://schema.org/" typeof="LocalBusiness">
<h2>Contact us!</h2>
<address property="email">
<a href="mailto:us@example.com">us@example.com</a>
</address>
<address property="address" typeof="PostalAddress">
<p property="streetAddress">123 Main St., Suite 404</p>
<p>
<span property="addressLocality">Yourtown</span>,
<span property="addressRegion">AK</span>,
<span property="postalCode">12345</span>
</p>
<p property="addressCountry">United States of America</p>
</address>
</section>
</footer>
If you ask me, that's 100x more readable than the original example, and it's going to be 100x more effective for SEO and accessibility purposes, too.
These are by no means the only semantic elements in HTML. There are lots of additional elements that help to tag and structure your text content, embedded media, etc. Here are a few to check out if you're enjoying this and want to dig deeper. You might recognize a few:
And that's just a start! Like I said, when you start reading the HTML spec, it's tough to stop. It's an incredibly rich language, and I think people underestimate it a little too often.

Latest comments (128)
header
Use: For defining introductory content or a set of navigational links.
Best for: Wrapping site headers, page headers, or section headers.
nav
Use: For defining a block of navigation links.
Best for: Primary navigation menus, secondary navigation, or any grouping of navigation links.
section
Use: For defining a section of content, typically with a heading.
Best for: Grouping related content within an article or page, such as different topics or themes.
article
Use: For defining self-contained content that could be distributed or reused independently.
Best for: Blog posts, news articles, forum posts, or any other independent content.
aside
Use: For defining content that is tangentially related to the content around it.
Best for: Sidebars, pull quotes, advertisements, or any other related content.
footer
Use: For defining footer content for a section or a page.
Best for: Site footers, page footers, or section footers, including copyright information, links, and metadata.
- main
Use: For defining the main content area of a document.
Best for: The primary content of a page, excluding headers, footers, and sidebars.
address
Use: For providing contact information for the author or owner of a document.
Best for: Physical addresses, email addresses, or other contact details.
details
Use: For specifying additional details that the user can view or hide.
Best for: Collapsible content such as FAQs, additional information, or interactive disclosures.
- summary
Use: For providing a summary or legend for the element.
Best for: The clickable heading for a block that expands or collapses the content.
- mark
Use: For highlighting or marking text that has relevance or importance.
Best for: Search results highlights, text annotations, or other emphasis needs.
All of my provided div alternatives are compatible with Google Chrome, Mozilla Firefox, Microsoft Edge, Safari, Opera and more...
I didnt know you could put header and footer inside an . Why is that? And what other semantic elements follow that pattern and what are the effects of it?
Hi! I'd be happy to answer your question but it looks like you typed a tag at one point and it got filtered out. Put a header and footer inside what?
oh sorry, I meant inside an "article" tag... it seems that tag works like some kind of isolated block independent from its html around it?
Gotcha! So the
<header>and<footer>tags are semantic ways of marking a header and footer of any segment of the page that needs one.<header>is definitely used way more frequently. Any body of text large enough that you'd want to break it into sections can be written with<section>tags and use a<header>to wrap the section heading, especially if you want to add something other than just a heading at the top of each section (like a section link to add a # section to the URL, a "back to top" link, an icon, anything like that).As for the purpose of the
<article>tag, like I mentioned in my post, their purpose is to wrap a section of the page (usually primarily text, but not necessarily) that is important content and is relatively independent from the rest of the page. The way I like to think about it is this: would this still make sense on its own if it were plucked out of the host page and dropped into another page, without the context of the other page? If so, maybe it could be wrapped in an<article>.Obviously a common use case is actual articles, e.g. news articles or blog posts. But another good example is Twitter. If you're on a laptop or desktop right now, open twitter.com in a new tab, right-click on a tweet and hit Inspect. You'll see that Twitter wraps each tweet in an
<article>tag. That's because a tweet is an independent unit that makes sense if you pluck it out of the context of twitter.com specifically and drop it into another page, as often happens with embedded tweets in news articles.Unfortunately that's where the semantic HTML stops for Twitter. The markup of a tweet is a perfect example of the div soup that made me want to write this article. I think a tweet is a perfect place to use semantic HTML. Something like this would be awesome:
This probably isn't everything, some extra elements (maybe even divs!) might be needed for structural and styling purposes, but these days honestly not very much more.
Here's how my rough markup would map to a real tweet:
Hope that helps!
Superb!!! Thank you! It feels like writing HTML is like writing in MarkDown, which is easier (in my opinion).
A better approach is to use microformats over RDFa for semantically marking up content. It is more modern, easier to learn, and less verbose to write.
From the link:
"Microformats2 is an update to microformats that provides a simpler way of annotating HTML structured syntax & vocabularies than previous approaches of using RDFa and microdata which require learning new attributes."
Wow, absolutely! I hadn't come across microformats specifically in my research, but it looks pretty powerful and straightforward. Do you know anything about technologies that recognize and utilize them, whether a11y assistants or search engines or anything else?
Hi Ken. This article was really great. I'm super new to HTML/CSS (less then a week!) and I found it really informative and easy to read. I'm currently taking Le Wagons Full-Stack Web Developer program. (Part time!)
The only confusing part for me about the article is how to write the CSS code to style these new sections. Maybe a quick primer or best practices link for for CSS styling based on this HTML?
For example... if you styled the h1 tag would that cover the h1 tag in and ?
And if you wanted to do the h1 tag in main only you it would be something like .main .article .header . h1? Does this add a lot of complexity to the CSS code?
Thanks!
Hey Bryan! Great questions, very fundamental to understand how CSS interacts with HTML. I won't be able to fully answer in a comment, because you've really struck at the heart of CSS selectors and how they work and I really recommend going through a full CSS tutorial for that, but I'll try to cover the main points.
The most important thing to remember is that CSS selectors are greedy, in a technical sense, meaning that they try to grab as much as they can. Anything that could possibly fit within the definition of a selector will. So if you write this block of CSS:
then every
<h1>tag on the whole page will be turned red, except where you define other blocks with more specific selectors that override the color, such as:This is a core term to know in CSS: specificity. Emma Wedekind wrote a great article going over it, which I highly recommend: CSS Specificity. But the basic idea is this: More specific selectors are stronger.
main h1beatsh1because it's more specific.h1says, "modify all<h1>tags";main h1says, "modify all<h1>tags within<main>". More specific, so stronger. (Emma's article covers the details on exactly how specificity is determined for a selector, so check that out.)To answer your specific cases:
Yes, an
h1selector applies to every<h1>on the page. Though remember that any properties can be overridden in specific cases by more specific selectors.You're mostly correct about styling that specific
<h1>, but remember that.mainis not the same asmain: the dot prefix refers to HTML classes, so if you used the selector.article, that would not match<article>, but would match<div class="article">. The better way to style the<h1>in this case:would be like this:
Hope that helps! As for best practices, that's an even bigger question, and there are a thousand different opinions out there. To be honest, I wouldn't worry about best practices and conventions for now; focus on learning how CSS itself actually works at a deep level before you get into the subjective stuff.
Hope this helps!
awesome ...
use multi header and footer is not negative point for seo ??
i wanna use section , header & footer for each section(semantic web) but i scare that it has a negative affect in Seo
😊
Many thanks for the article! Good job!
Nice breakdown! I've been using some for a while now, but others I barely knew. Thanks for sharing!
Awesome post dude!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.