In this article · 5 sections
Most visitors to small business websites in India come from phones, so the menu must work perfectly on small screens. This tutorial builds a responsive navbar with a hamburger toggle, without frameworks.
HTML
<header class="site-header">
<a href="/" class="logo">Joboo Taxi</a>
<button class="nav-toggle" aria-expanded="false" aria-controls="main-nav" aria-label="Open menu">
<span></span><span></span><span></span>
</button>
<nav id="main-nav" class="main-nav" aria-label="Main">
<a href="/">Home</a>
<a href="/routes">Routes</a>
<a href="/fleet">Our Fleet</a>
<a href="/contact">Contact</a>
<a href="tel:+919876543210" class="nav-call">Call Now</a>
</nav>
</header>
A real <button> makes the toggle keyboard and screen-reader friendly. See semantic HTML.
CSS (mobile first)
.site-header{position:sticky;top:0;z-index:50;display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#fff;box-shadow:0 1px 8px rgba(0,0,0,.08)}
.logo{font-weight:800;font-size:20px;color:#111;text-decoration:none}
.nav-toggle{display:flex;flex-direction:column;gap:5px;background:none;border:0;padding:8px;cursor:pointer}
.nav-toggle span{width:24px;height:2px;background:#111;transition:transform .2s,opacity .2s}
.main-nav{position:absolute;top:100%;left:0;right:0;display:none;flex-direction:column;background:#fff;padding:8px 16px 16px;box-shadow:0 8px 16px rgba(0,0,0,.08)}
.main-nav.open{display:flex}
.main-nav a{padding:12px 0;color:#222;text-decoration:none;border-bottom:1px solid #eee}
.nav-call{margin-top:8px;text-align:center;background:#f5c400;border-radius:8px;font-weight:700;border:0}
.nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
@media (min-width: 900px){
.nav-toggle{display:none}
.main-nav{position:static;display:flex;flex-direction:row;gap:24px;align-items:center;padding:0;box-shadow:none}
.main-nav a{border:0;padding:8px 0}
.nav-call{margin:0;padding:10px 18px}
}
For layout concepts, see Flexbox vs Grid.
JavaScript
const toggle = document.querySelector('.nav-toggle');
const nav = document.querySelector('#main-nav');
toggle.addEventListener('click', () => {
const open = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', String(!open));
toggle.setAttribute('aria-label', open ? 'Open menu' : 'Close menu');
nav.classList.toggle('open', !open);
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && nav.classList.contains('open')) {
nav.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
toggle.focus();
}
});
Improvements
- Highlight the current page with
aria-current="page" - Close the menu after a link is tapped (for one-page sites)
- Keep the Call and WhatsApp buttons visible on mobile; they drive leads. See contact page design
- Test with keyboard Tab and a screen reader. See accessibility basics
FAQs
Should I use Bootstrap's navbar instead?
It's fine if you already use Bootstrap. See Bootstrap 5 tutorial. For a light site, this custom version avoids extra CSS and JS.
Why position: sticky?
It keeps the menu visible while scrolling without the layout jumps of position: fixed.
Was this article helpful?
Your answer helps us improve our guides