A navigation bar helps visitors move between the main pages of a website. In this beginner project, you will use CSS Flexbox to place several links in a row and make them wrap neatly on a narrow screen.
What you will learn
By the end of this lesson, you will know how to:
- Turn a list into a horizontal navigation bar
- Create space between navigation links
- Allow links to wrap on smaller screens
- Add clear hover and keyboard-focus styles
- Troubleshoot common Flexbox mistakes
You only need a text editor and a web browser. Save the complete example below as navigation.html, then open it in your browser.
Complete example to try locally
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My Flexbox navigation</title>
<style>
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: #172b3a;
background: #ffffff;
}
header {
padding: 20px;
color: #ffffff;
background: #145da0;
}
header h1 {
margin: 0 0 16px;
font-size: 1.6rem;
}
nav ul {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin: 0;
padding: 0;
list-style: none;
}
nav a {
display: block;
padding: 10px 14px;
color: #ffffff;
text-decoration: none;
background: #0d477d;
border-radius: 6px;
}
nav a:hover {
background: #08345d;
}
nav a:focus-visible {
outline: 3px solid #ffdf70;
outline-offset: 3px;
}
main {
max-width: 720px;
margin: auto;
padding: 24px;
}
</style>
</head>
<body>
<header>
<h1>My learning website</h1>
<nav aria-label="Main navigation">
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="html.html">HTML</a></li>
<li><a href="css.html">CSS</a></li>
<li><a href="javascript.html">JavaScript</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<main>
<h2>Welcome</h2>
<p>Use the navigation links to explore the different sections of this practice website.</p>
</main>
</body>
</html>
What should appear?
You should see a blue header containing the website title and five navigation links. The links appear next to one another with equal spacing between them.
Make the browser window narrower. When the links no longer fit on one line, they should move onto another line instead of disappearing outside the screen.
The example links point to sample HTML filenames. They will only open real pages if you create files with those names.
How Flexbox arranges the links
The important declaration is:
display: flex;
We apply it to the ul, which is the parent of all the list items. Its direct children—the li elements—become Flexbox items.
The following declaration allows those items to continue on another line:
flex-wrap: wrap;
Without it, the browser tries to keep every item on one row. That can make the navigation difficult to use on a narrow screen.
The gap property creates space between the items:
gap: 12px;
This is simpler than adding a different margin to every link.
Keep the HTML structure meaningful
Although the navigation appears as a row, it is still a list of related links. That is why the example uses nav, ul, li, and a elements.
The label in this line describes the purpose of the navigation:
<nav aria-label="Main navigation">
A page can contain more than one navigation area. Clear labels help assistive technologies distinguish the main navigation from links in a footer or sidebar.
Hover and keyboard focus
The :hover rule changes the link background when a visitor points at it with a mouse:
nav a:hover {
background: #08345d;
}
Keyboard users also need a visible indication of the selected link. The :focus-visible rule adds a yellow outline when a link receives keyboard focus.
Press the Tab key repeatedly to test this. Each navigation link should receive a visible outline. Do not remove outlines unless you replace them with an equally clear focus style.
Common problems and solutions
The links still appear vertically
Check that display: flex is applied to nav ul, not just to one individual link.
Bullet points are still visible
Make sure the list has list-style: none. Also remove the list’s default spacing with margin: 0 and padding: 0.
The links leave the screen on a phone
Confirm that flex-wrap: wrap is present. Also check that the page contains the viewport meta element.
The link background only covers the text
Add display: block to nav a. This allows its padding to form a larger clickable area.
A link opens a “file not found” page
The filename in href must match the real file. Capitalization can matter after uploading the website. For example, CSS.html and css.html may be treated as different files.
Exercise: move Contact to the right
On a wide screen, you can use an automatic margin to place the final item at the right side of the navigation bar.
Add a class to the Contact list item:
<li class="contact-link">
<a href="contact.html">Contact</a>
</li>
Then add this CSS:
.contact-link {
margin-left: auto;
}
Refresh the page. Contact should move to the right when enough space is available.
Now make the window narrow again. Check whether the wrapping still produces a useful layout. Responsive testing is important because a change that looks good on a large screen may behave differently on a phone.
Extend the navigation
Try adding an About link:
<li><a href="about.html">About</a></li>
Place it before Contact. Then create a simple about.html file so the link has a real destination.
You can also experiment with the gap, background colours, padding, and corner radius. Change one value at a time, save the file, and refresh the browser so you can see what each declaration does.
Continue practising
When the navigation works correctly, move the CSS rules into a separate style.css file. This lets several pages share the same navigation design.
Continue with A Separate style.css File, or return to the CSS examples on Playcode123.com to review the basic syntax.
Further reference: MDN’s guide to the basic concepts of Flexbox.