Semantic HTML - The <nav> Element

Chapter 23 19 mins

Learning outcomes:

  1. What is the <nav> element
  2. Examples of using <nav>
  3. Why use <nav> instead of <div>
  4. Things to note regarding <nav>

The <nav> element is perhaps one of the most useful semantic elements in HTML. It's used, or at least should be used, on all websites out there.

But what exactly is <nav>?

The term 'nav' stands for 'navigation' and basically means that the <nav> element is concerned with marking up a navigation section in an HTML document.

In this respect, a navigation section is simply a group of links that allows us to navigate across the entire underlying website or across the current page (for example, go to the first section or the last section).

For example, in almost every other website we visit, there is a navigation section in the header, next to the logo, typically comprised of links rendered in the same line, as illustrated below:

A navigation section in the header of a webpage.
A navigation section in the header of a webpage.

The blue-bordered box at the right side of the website's logo represents the navigation menu. This is often referred to as a navigation bar, or more concisely as a navbar. This section is a perfect candidate for <nav>.

Customarily, it's never the case that a navigation section is comprised of just one link, as even the illustration above showcases — we have many such links.

In that sense, we could say that navigation sections are comprised of lists of links.

So to define it formally that why is <nav> used in HTML:

The <nav> element is used to denote a list of navigation links.

Quoting from the official HTML standard:

The nav element represents a section of a page that links to other pages or to parts within the page: a section with navigation links.

Now, navigation sections aren't just limited to being in the header. In fact, even within the header, we can have multiple such sections.

For example, a 'table of contents' section in HTML documents is also a perfect candidate for <nav>. It allows us to navigate across different sections within the same document.

Consider the table of contents displayed on the left side on this page (the one you're current reading), if you're viewing the page on desktop — it's denoted using the <nav> element.

Apart from this, yet another example of using <nav> could be to denote a breadcrumbs menu for a webpage, as follows:

A breadcrumbs menu on a webpage.
A breadcrumbs menu on a webpage.

A breadcrumbs menu, or simply breadcrumbs, indicates the path hierarchy leading to the current webpage, with individual links pointing to given webpages in the hierarchy.

For instance, if we start at the home page of an online shopping store, then go over to the products page, and then open up a page showcasing all books, we might get a breadcrumbs menu similar to the following:

A breadcrumbs section
A breadcrumbs section

Akin to navigation bars (in the header), the breadcrumbs menu is also pretty common across websites since it allows users to quickly see their current position within the website.

An important thing to keep in mind is that even though navigation sections can be marked up using the generic, monotonous <div> element, we shouldn't be doing so. For marking up a navigation section, we should only use <nav>.

But why? This we shall answer in more detail later on in this chapter.

Moving on, as with <article>, <aside>, and <section>, the <nav> element is a sectioning content element in HTML. That is, <nav> is used to define the scope of <header> and <footer> elements nested inside it.

In addition to this, as we can probably guess, <nav> is a block-level element.

Let's now consider some examples of the <nav> element.

Examples of the <nav> element

Say we want a section of navigation links (also known as a navigation bar) in the header of a webpage. This is an extremely common use case of <nav>.

In the following code, we present such an example. We have a very basic HTML document, containing a header and a footer and some text in between:

<header style="background-color: pink">
   <p>The header</p>
   <nav>
      <ul>
         <li><a href="#About">About</a></li>
         <li><a href="#Contact">Contact</a></li>
      </ul>
   </nav>
</header>

<main>
   <h1>A heading</h1>
   <p>A small piece of text.</p>
</main>

<footer style="background-color: pink">The footer</footer>

The header contains a section, denoted using <nav>, comprised of two navigation links as part of an unordered list (<ul>).

Live Example

Take note of this <ul> element inside <nav>. Since <nav> denotes a list of navigation links, it's desirable to have a <ul> inside of it to annotate the list of links.

<nav>
   <ul>
      <li><a href="#About">About</a></li>
      <li><a href="#Contact">Contact</a></li>
   </ul>
</nav>

However, it's not mandatory to do so. The following <nav> is perfectly valid:

<nav>
   <a href="#About">About</a>
   <a href="#Contact">Contact</a>
</nav>

While both of these are fine, the first one, where we have a list element inside <nav>, is much better. The following section answers the question why.

Why have <ul> (or <ol>) inside a <nav>?

As we learnt at the start of this chapter, <nav> denotes a navigation section, and a navigation section is typically comprised of more than one link — it's essentially a list of links.

Likewise, we must use a list element in HTML — <ul> or <ol> — inside a <nav> element for representing a list of navigation links.

Firstly, it clearly conveys the semantics of the underlying content, i.e. that the <nav> represents a list of some stuff.

Secondly, it again helps in the accessibility of the webpage, in this case of the navigation section. A screen reader typically reads out the total number of items in a list (<ul> or <ol>) before proceeding with the individual items. When used inside a navigation section, this helps the user rightaway know about the total number of links in the navigation section.

Over to example number two.

We talked about a table of contents section in the previous discussion. Let's now try emulating one in a hypothetical setting.

Below we have a snippet of HTML representing a document teaching HTML:

<header>
   <h1>Learning HTML</h1>
</header>

<section id="s1">
   <h2>What is HTML?</h2>
   <p>...</p>
</section>

<section id="s2">
   <h2>Which code editor to use?</h2>
   <p>...</p>
</section>

<section id="s3">
   <h2>The basics of HTML</h2>
   <p>...</p>
</section>

The document contains three level-2 headings, each denoting different aspects of learning HTML (for e.g. what is HTML, which editor to use for coding HTML, and so on).

These level-2 headings together form the document's outline. To give a quick overview of the contents of the document, we want to take this outline and present it right at the start of the document, entitled 'Table of contents.'

This table of contents section would be a list. Each <h2> heading's content would be used to create a list item, and obviously an anchor as well to take us to the corresponding section in the document.

To represent this table of contents section, we'll use the <nav> element with an <ol>. Each list item would contain an <a> element, pointing to the corresponding section in the document via its own href and an id on the section.

Here's the new HTML:

<header>
   <h1>Learning HTML</h1>
<p>Table of contents:</p> <nav> <ol> <li><a href="#s1">What is HTML?</a></li> <li><a href="#s2">Which code editor to use?</a></li> <li><a href="#s3">The basics of HTML</a></li> </ol> </nav>
</header> <section id="s1"> <h2>What is HTML?</h2> <p>...</p> </section> <section id="s2"> <h2>Which code editor to use?</h2> <p>...</p> </section> <section id="s3"> <h2>The basics of HTML</h2> <p>...</p> </section>

Live Example

This time the list makes a lot more sense than in the previous example. That's because a table of contents section is already a 'list' of contents at a glance, and therefore, there's nothing better than using an HTML list element to represent it.

We're using <ol> instead of <ul> here because the order of items in the table of contents matters. The first item appears first in the document, the second one appears second, and so on; thus, it makes more sense to go with <ol>.

Having grasped a solid amount of knowledge from these examples, it's now time to look into some things to take note of when working with the <nav> element.

Why use <nav> instead of <div>?

Of course, the <nav> element is a semantic counterpart to using the boring <div> for presenting a navigation section in an HTML document, and in that right we must prefer it over <div>.

But this isn't that strong of an argument in favor of <nav> to get us to promptly rethink our decision of denoting a navigation section using a <div> instead.

The question stands: Why use <nav> over <div>?

Fortunately, the answer is very simple.

Being a semantic element, <nav> improves the accessibility of a webpage unlike the <div> element. Here's how...

<nav> represents a landmark in an HTML document — specifically, a navigation landmark.

Assistive technologies, like screen readers, process a page as a set of landmarks, giving quick access to users for navigating between those landmarks. For example, the main header of a webpage is a landmark — the header landmark; the main footer of a webpage is a landmark — the contentinfo landmark; and so on.

In the case of <nav>, it denotes a navigation landmark. Screen reader users get the ability to easily move between the various navigation landmarks in an HTML document via keyboard shortcuts.

For example, a user (on a screen reader) might want to skip to the second navigation menu in a document. In this case, he can simply leverage the ability of his screen reader software to take him to the second navigation landmark directly, that is, the second <nav>, and then read it out.

Clearly, the <div> element doesn't enjoy such a privilege. It does NOT create a navigation landmark, even though it might well wrap up a navigation section in the HTML.

There is absolutely no trivial way for the browser to figure out that a particular <div> element containing a bunch of links represents a navigation section. It might well represent just a collection of links pointing to external resources as part of a blog post's text.

To boil it down, every single navigation section of a webpage must be denoted via the <nav> element.

It improves the accessibility of the document and clearly demarcates navigation sections from the rest of the document's content.

Things to note regarding <nav>

It's valid to have multiple <nav>s

As per the HTML standard, it's completely OK to have more than one <nav> element in an HTML document. Even if you think about it, this makes sense. (Always try reasoning about given things.)

Customarily, many websites tend to have two navigation sections on their site's pages — one in the header, one in the footer. Both these sections are candidates for the <nav> element, giving us a total of two <nav>s.

An extremely important thing to note here is that if we have more than one <nav> element, it's utmost necessary for us to label the <nav> elements to make their purpose clear (to screen readers).

"Why?" you ask.

Why do we need to label <nav>s when there are multiple of them?

Think from the perspective of a screen reader user and the reason will be crystal clear.

Imagine we have three <nav> elements on a webpage. The user leverages the feature of his screen reader software to navigate to the first <nav>. The software reads out 'navigation'. Alright. He then transitions to the next <nav> and the software again reads out 'navigation'.

Hmm. There was a 'navigation' before as well and a 'navigation' now. "What is the difference between these navigation sections?" thinks the user.

To his surprise, navigating to the third <nav> again reads out 'navigation'. At this point, it's completely poor of a setup by the webmaster to have not labeled each <nav> element's purpose clearly.

This is the issue when we have more than one <nav> element on a webpage.

In the case of just one <nav>, the user won't be concerned much with whether it's labeled or not — after all, there is just one time 'navigation' is read out and so the user can well assume that the section represents the main navigation of the webpage.

But when we have multiple <nav>s, hearing the same generic 'navigation' label would confuse the user and obfuscate the purpose of each <nav>.

In order to label a <nav>, we can either use the aria-labelledby attribute or the aria-label attribute. Both attributes label the element on which they're set.

aria-labelledby points to some other element for the label text. In particular, it contains the id of the element that contains the label text.

For instance, if a <nav> element represents a webpage's main navigation, and has an <h2> in it that clearly describes its purpose, for e.g. via text like 'Main navigation', we can set aria-labelledby to point to this <h2> element.

Following is a concrete example:

<header>
   <nav aria-labelledby="header-nav-heading">
      <h2 id="header-nav-heading">Main navigation</h2>
      ...
   </nav>
</header>

...

<footer>
   <nav aria-labelledby="footer-nav-heading">
      <h2 id="footer-nav-heading">Footer navigation</h2>
      ...
   </nav>
</footer>

We have two <nav> sections on the webpage, one inside <header> and one inside <footer>. To distinguish between them, we use aria-labelledby on each of the <nav>s, describing their purpose by pointing to the corresponding, labelling <h2> element.

The aria-label attribute is useful when we don't have any existing element containing the text to label an element. In this case, aria-label itself contains this text.

Consider the following rewrite of the example code above:

<header>
   <nav aria-label="Header navigation">
      ...
   </nav>
</header>

...

<footer>
   <nav aria-label="Footer navigation">
      ...
   </nav>
</footer>

We put the label text directly in each of the <nav>s because this time we don't have any <h2>s (or any other elements) containing the label text.

If we have any element that contains text suitable to label a given <nav>, we should definitely use aria-labelledby over aria-label in order to prevent duplicating the text.

One might wonder whether it's possible to nest <nav> inside <nav>. What do you think?

Well, based on the current HTML standard, it indeed is possible to nest a <nav> element inside another <nav> element.

For example, the following code is perfectly valid:

<nav class="nav">
   <ul>
      <li>
         <a href="#">Courses</a>
<nav class="sub-nav"> <!-- This is valid. --> <ul> <li><a href="/courses/html/">HTML</a></li> <li><a href="/courses/css/">CSS</a></li> <li><a href="/courses/js/">JavaScript</a></li> </ul>
</nav> </li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav>

However, it's not very common to see <nav>s being nested inside <nav>s.

<nav>s shouldn't be used for all lists of links

While a <nav> element is used to represent a list of navigation links on a webpage, this doesn't at all mean that we should use it to denote every single list of links.

Remember that <nav> is meant to denote whole sections of navigation links in HTML, NOT to encapsulate every other set of links.

Plus, the links in <nav> should really be 'navigation' links, i.e. the ones pointing to other areas of the website or the current page so that users can easily navigate across the website.

In that sense, take at the look at the following code, where we have a list of two links, presenting external resources to further read about a concept in HTML, in a hypothetical blog article:

<p>Here are some external resources to learn HTML <code>&lt;nav&gt;</code> from:</p>

<nav> <!-- This doesn't make sense here! -->
   <ul>
      <li><a href="https://example.com/resource-a">Resource A</a></li>
      <li><a href="https://example.com/resource-b">Resource B</a></li>
   </ul>
</nav>

<p>Once you're done with these continue reading below.</p>

Since this set of links doesn't denote navigation for the underlying website, we should NOT use <nav> to represent it.

Here's a better version of the code, eliminating the <nav>:

<p>Here are some external resources to learn HTML <code>&lt;nav&gt;</code> from:</p>

<ul> <!-- Much better now, without the <nav> -->
   <li><a href="https://example.com/resource-a">Resource A</a></li>
   <li><a href="https://example.com/resource-b">Resource B</a></li>
</ul>

<p>Once you're done with these continue reading below.</p>

Much simpler and semantically sensible now!

"I created Codeguage to save you from falling into the same learning conundrums that I fell into."

— Bilal Adnan, Founder of Codeguage