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:

  1. Use aria-expanded="false" on the toggle button and update it with JS
  2. Ensure all links are reachable via Tab
  3. Add a visible :focus style 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.