This tutorial describes how to build an accessible main navigation of a website. You learn about semantic HTML, accessibility, and how using ARIA attributes can sometimes do more harm than good.

There are many different ways of building the main navigation of a website, in terms of styling, functionality, and the underlying markup and semantic information. If the implementation is too minimalist, it works for most people, but the user experience (UX) might not be great. If it’s over-engineered, it might confuse users or even hinder them from being able to access it at all.

For most websites, you want to build something that’s neither too simple, nor too complicated.

Building layer by layer

In this tutorial you start with a basic setup and add features layer by layer up to a point where you provide just enough information, styling, and functionality to please most users. To achieve that you make use of the progressive enhancement principle, which states that you start with the most fundamental and robust solution and progressively add layers of functionality. If one layer fails to work for some reason, the navigation will still work because it gracefully falls back to the underlying layer.

Basic structure

For a basic navigation you need two things: <a> elements and a few lines of CSS to improve the default styling and layout of your links.


<a href="/home">Home</a>
<a href="/about-us">About us</a>
<a href="/pricing">Pricing</a>
<a href="/contact">Contact</a>


/* Define variables for your colors */
:root {
	--color-shades-dark: rgb(25, 25, 25);

/* Use the alternative box model
Details: <> */
* {
	box-sizing: border-box;

/* Basic font styling */
body {
  font-family: Segoe UI, system-ui, -apple-system, sans-serif;
  font-size: 1.6rem;

/* Link styling */
a {
  --text-color: var(--color-shades-dark);

  border-block-end: 3px solid var(--border-color, transparent);
  color: var(--text-color);
  display: inline-block;
	margin-block-end: 0.5rem; /* See note at the bottom of this chapter */
  margin-inline-end: 0.5rem;
	padding: 0.1rem;
	text-decoration: none;

/* Change the border-color on :hover and :focus */
a:where(:hover, :focus) {
  --border-color: var(--text-color);

View “Step 1: Basic HTML and CSS” on CodePen.

This works well for most users, no matter how they’re accessing the site. The navigation is accessible with a mouse, a keyboard, a touch device, or a screen reader, but there's room for improvement. You can enhance the experience by extending this basic pattern with additional functionality and information.

Here’s what you can do: