How to make a horizontal menu from a list
Short answer
Remove the list bullets and indent and line the items up with flexbox:
<style>
.menu { display: flex; gap: 20px; margin: 0; padding: 0; list-style: none; }
.menu a { color: inherit; text-decoration: none; }
.menu a:hover { color: steelblue; }
</style>
<nav>
<ul class="menu">
<li><a href="#">Home</a></li>
<li><a href="#">Catalog</a></li>
<li><a href="#">Contacts</a></li>
</ul>
</nav><nav> marks the block as navigation: screen readers let users jump to it with one key.
Separators and the current page
A separator is added with a pseudo-element to every item except the first. The current page is marked with aria-current="page", and the same attribute is used to highlight it:
<style>
.menu { display: flex; gap: 12px; padding: 0; list-style: none; }
.menu li + li::before { content: "·"; margin-right: 12px; color: gray; }
.menu [aria-current] { font-weight: 700; color: inherit; text-decoration: none; }
</style>
<ul class="menu">
<li><a href="#">Home</a></li>
<li><a href="#" aria-current="page">Blog</a></li>
<li><a href="#">About</a></li>
</ul>Many items
If the items do not fit in a row, flex-wrap: wrap moves them to the next line. On phones a long menu is usually hidden behind a button.
Common mistake
The menu links are kept small — only the text itself is clickable. Give the links padding (and display: block) to make the tap area larger, especially for a finger on a touch screen.
Functions used in this recipe
- <nav> — A block of main navigation: the site menu, a table of contents, breadcrumbs.
- <ul> — A bulleted list: items whose order does not matter.
- display — Decides how an element behaves in the flow and how it lays out its content.
- gap — The gaps between items in flexbox and grid.
- aria-* — Accessibility attributes: the role, name and state of an element for screen readers.