Menu

HTML nav Tag: Navigation Bars, Menus and Breadcrumbs

The <nav> element marks a block of major navigation links. Learn how to build a navigation bar with <nav> and a list, how to mark the current page, how to label several navs on one page, and how to make a mobile menu toggle.

This page includes runnable editors - edit, run, and see output instantly.

A navigation bar with nav

Wrap your menu in <nav> and put the links in a list. Flexbox turns the list into a horizontal bar:

list-style: none and padding: 0 remove the bullets and the indent. display: block on each link lets its padding take up real space in the bar, so the whole padded box is the click target. Delete the display: flex line and the same menu becomes a vertical list, which is what a sidebar menu looks like.

<nav> itself looks like nothing. Its job is meaning: screen readers expose it as a navigation landmark, so a user can jump to the menu, or past it, with one key.

Mark the current page

Add aria-current="page" to the link for the page being shown. It tells screen readers "you are here", and it gives CSS a hook to highlight the link:

Move aria-current="page" to another link and the highlight follows it. Styling the attribute instead of an .active class keeps the look and the accessibility in sync: you cannot have one without the other.

Several navs on one page: labels and breadcrumbs

A page can have a main menu, breadcrumbs and a table of contents, each in its own <nav>. Give each one an aria-label, so a screen reader announces "Breadcrumb navigation" instead of three identical "navigation" entries:

Breadcrumbs use an ordered list <ol> because the order matters. The slashes come from CSS ::before, so screen readers do not read "slash" between every item. The last item is the current page and is not a link.

A table of contents

A list of links to sections of the same page is navigation too. #id links jump to the element with that id; try them in the preview:

Here the label comes from a visible heading with aria-labelledby, which is better than aria-label when the heading is already on screen.

A mobile menu toggle

On narrow screens, menus usually hide behind a button. Use a real <button> with aria-expanded, and keep the links inside <nav>:

aria-expanded tells a screen reader whether the menu is open, and the hidden attribute removes the list from both the screen and the accessibility tree while it is closed. On wide screens you would show the list with a media query and hide the button.

Common mistakes

  • Wrapping every link group in <nav>. Use it for the main menu, breadcrumbs, pagination and tables of contents. Inline links in text are not navigation blocks.
  • A menu button made from a <div>. It cannot be focused or pressed with the keyboard. Use <button>.
  • Several navs without labels. Add aria-label or aria-labelledby to each so they can be told apart.
  • Only coloring the current link. Add aria-current="page"; color alone is not announced and may not be visible to everyone.
  • Links with href="#" in production. They are fine in a demo, but real menu items need real URLs so they work when opened in a new tab. The links page covers how href values work.

Frequently Asked Questions

What is the nav tag in HTML?

<nav> is a semantic element that wraps a block of major navigation links, such as the site menu, a table of contents or breadcrumbs. Screen readers list it as a navigation landmark so users can jump straight to it.

Should links inside nav be in a list?

It is the common pattern and a good one: a <ul> of <li> items lets screen readers announce how many links the menu has. Plain links directly inside <nav> are also valid, for example for two or three links in a row.

Does every group of links need a nav element?

No. Use <nav> for major navigation blocks only. A few links in a paragraph or a short list of legal links in the footer do not need it, and too many nav landmarks make each one harder to find.

How do I make a horizontal navigation bar?

Put the links in a <ul> inside <nav>, then give the list display: flex; list-style: none; padding: 0; and a gap. Flexbox lays the items out in a row.

How do I show the current page in a navbar?

Add aria-current="page" to the link for the page the user is on, and style it with the selector [aria-current="page"]. Screen readers then announce it as the current page too.

Can a page have more than one nav?

Yes, for example a main menu, a breadcrumb trail and a table of contents. Give each one a different aria-label such as "Main" or "Breadcrumb" so screen reader users can tell them apart.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED