HTML navigation menu generator with submenus and aria-current

Write one "Label | URL" line per link and indent two spaces for a submenu to get a nav element with a properly nested list, an aria-label naming the menu, and aria-current="page" on the link to the page the visitor is on.

Live demo · real result from this tool

Press Generate to create a result.

Processed on your device — nothing is uploaded.

How to use the nav menu generator

  1. In Label | URL per line (indent 2 spaces for a submenu), write each link, for example Blog | /blog.
  2. Indent child links by two spaces under their parent.
  3. Set the aria-label, such as “Main” or “Footer”.
  4. Enter the Current page URL (gets aria-current) for the page this menu will appear on.
  5. Optionally change the Class on <nav>, then copy the code.

What it does and when to use it

Almost every site has a main menu, and many have a footer menu, a sidebar of documentation links or a menu for an account area. All of them share the same accessible pattern: a nav landmark with a name, a list of links, nested lists for sub-pages, and a marker on the current page. The generator writes that pattern from a plain outline, so you can focus on the labels and URLs.

Pair it with the HTML5 Semantic Layout Generator, which places a menu inside the page header. For a single link with rel or target options, use the HTML Link Generator. To check every href on a finished page, the HTML Attribute Extractor lists them with their line numbers.

How it works

The lines are turned into nested lists with the same indentation rules as a list generator: every two spaces or one tab is one level, and a sub-list is placed inside its parent’s li. Each line is split at | into label and URL. A line without a URL gets href="#", which is useful for a parent that only opens a submenu, though a button is better for that in a finished menu. The link whose URL equals Current page URL gets aria-current="page". class and aria-label are left out when empty. Text and URLs are HTML-escaped, and the result is built in your browser.

Worked examples

A two-link menu on the About page:

<nav class="site-nav" aria-label="Main">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about" aria-current="page">About</a></li>
  </ul>
</nav>

A submenu. In the sample, PDF and Images are indented under Tools, and the current page is /tools:

<li><a href="/tools" aria-current="page">Tools</a>
  <ul>
    <li><a href="/pdf">PDF</a></li>

A parent without a URL. Docs with Install | /docs/install indented below it, and empty class, label and current URL, gives <nav> with no attributes and <li><a href="#">Docs</a> containing the sub-list.

Limits and tips

  • Generate the menu once per page, or set aria-current in your template, because the current page changes from page to page.
  • Keep link labels short and unique; “More” twice in one menu is confusing.

Frequently asked questions

What does aria-current="page" do?
It tells screen readers that this link points to the page being viewed; they announce it as "current page". It also gives you a reliable CSS hook, such as a[aria-current="page"], for highlighting the active item, as the preview does with bold and an underline.
Why does the nav need an aria-label?
Screen readers list each nav as a navigation landmark. When a page has several, such as a main menu, a breadcrumb and a footer menu, labels like "Main" and "Footer" let people pick the right one. Do not include the word "navigation" in the label, because it is announced anyway.
Does the generator make dropdown menus that open on hover?
It writes the nested list structure only. Showing and hiding submenus is up to your CSS or JavaScript. If you add a toggle button, give it aria-expanded so screen readers know whether the submenu is open.
Why is the menu a list?
A list tells screen readers how many links the menu has and where each one sits, for example "list, 4 items". Nested lists show which links belong to which parent, which plain links separated by spaces or bars cannot do.
How is the current link matched?
The Current page URL must equal the link's URL exactly. /tools matches /tools but not /tools/ or https://example.com/tools. Use the same form of URL in both places.

Written by the ToolsRift team · Last updated

Pages are drafted with AI assistance and checked by automated tests. How we write and check pages.

Was this tool useful?

Report a problem

Start typing to search every tool.

↑ ↓ to moveEnter to openEsc to close