What You'll Build
In this tutorial, you'll build a fully responsive navigation bar from scratch — one that displays a horizontal menu on desktop and collapses into a hamburger menu on mobile. No frameworks needed: just clean HTML, CSS, and a few lines of vanilla JavaScript.
Prerequisites
- Basic knowledge of HTML and CSS
- A code editor (VS Code recommended)
- A browser for testing
Step 1: The HTML Structure
Start with a semantic <nav> element containing your logo and an unordered list of links. Add a hamburger button for mobile.
<nav class="navbar">
<div class="nav-brand">MyBrand</div>
<button class="nav-toggle" aria-label="Toggle navigation">
<span class="hamburger"></span>
</button>
<ul class="nav-menu">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/services">Services</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
Step 2: The CSS — Desktop Layout
Style the navbar as a flexbox row on desktop. Hide the toggle button on larger screens.
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 2rem;
background-color: #0f172a;
}
.nav-brand { color: #fff; font-weight: 700; font-size: 1.25rem; }
.nav-menu { display: flex; list-style: none; gap: 2rem; margin: 0; }
.nav-menu a { color: #e2e8f0; text-decoration: none; }
.nav-menu a:hover { color: #f59e0b; }
.nav-toggle { display: none; }
Step 3: The CSS — Mobile Layout
Use a media query to switch to a stacked, hidden menu on small screens. The .is-open class will toggle visibility.
@media (max-width: 768px) {
.nav-toggle {
display: block;
background: none;
border: none;
cursor: pointer;
}
.hamburger,
.hamburger::before,
.hamburger::after {
display: block;
width: 24px;
height: 2px;
background: #fff;
position: relative;
}
.nav-menu {
display: none;
flex-direction: column;
width: 100%;
position: absolute;
top: 60px; left: 0;
background: #0f172a;
padding: 1rem 2rem;
}
.nav-menu.is-open { display: flex; }
}
Step 4: The JavaScript — Toggle Logic
Just a few lines to add and remove the is-open class when the button is clicked:
const toggle = document.querySelector('.nav-toggle');
const menu = document.querySelector('.nav-menu');
toggle.addEventListener('click', () => {
menu.classList.toggle('is-open');
});
Step 5: Accessibility Improvements
Good navbars are keyboard and screen-reader friendly. Add these enhancements:
- Use
aria-expanded="false"on the toggle button and update it with JS - Ensure all links are reachable via Tab
- Add a visible
:focusstyle for keyboard navigation
Next Steps
You now have a clean, functional responsive navbar. From here you can extend it with dropdown menus, active-link highlighting based on the current URL, or smooth CSS transitions for the mobile menu open/close animation. The core pattern stays the same.