What is a Navigation Bar?
A navigation bar (navbar) is the row of links at the top of a webpage that helps users move between sections or pages. Think of it like the menu at a restaurant — without it, visitors don't know where to go.
A well-built navbar should:
- Work on all screen sizes (desktop, tablet, mobile)
- Show a hamburger menu (☰) on small screens
- Be easy to read and click/tap
- Load fast — no heavy libraries needed
Why this matters for WordPress users: Even if you use Elementor or a theme, understanding how a navbar works in raw HTML/CSS gives you full control when you need to customize it — and it's a must-know skill for web developers.
What You'll Need
You don't need to install anything. Just create one file called index.html on your computer and open it in your browser. That's it.
| Tool | Purpose | Free? |
|---|---|---|
| VS Code | Code editor to write HTML/CSS/JS | ✅ Yes |
| Any browser | To preview your navbar live | ✅ Yes |
| Basic HTML knowledge | Tags like <nav>, <ul>, <li> | ✅ Free to learn |
HTML Structure
First, let's build the skeleton. We'll use the <nav> HTML5 tag — it's semantic, which means search engines and screen readers understand it's a navigation element.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>My Responsive Navbar</title> <link rel="stylesheet" href="style.css" /> </head> <body> <nav class="navbar"> <div class="nav-container"> <!-- Logo --> <a href="#" class="nav-logo">GrowWP</a> <!-- Navigation Links --> <ul class="nav-links" id="navLinks"> <li><a href="#" class="active">Home</a></li> <li><a href="#">Blogs</a></li> <li><a href="#">Tools</a></li> <li><a href="#">About</a></li> <li><a href="#">Contact</a></li> </ul> <!-- Hamburger Button (visible only on mobile) --> <button class="hamburger" id="hamburger" aria-label="Toggle menu"> <span></span> <span></span> <span></span> </button> </div> </nav> <script src="script.js"></script> </body> </html>
Pro Tip: Always add aria-label="Toggle menu" to your hamburger button. This helps visually impaired users who use screen readers understand what the button does.
CSS Styling (Desktop First)
Now create a file called style.css and add the following. We'll style the desktop view first, then handle mobile with media queries.
/* ── Reset & Base ── */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Inter', sans-serif; } /* ── Navbar ── */ .navbar { background-color: #1e293b; position: sticky; top: 0; z-index: 1000; box-shadow: 0 2px 12px rgba(0,0,0,0.2); } .nav-container { max-width: 1100px; margin: 0 auto; padding: 0 24px; height: 60px; display: flex; align-items: center; justify-content: space-between; } /* ── Logo ── */ .nav-logo { color: #ffffff; font-size: 1.3rem; font-weight: 700; text-decoration: none; letter-spacing: -0.5px; } /* ── Nav Links ── */ .nav-links { list-style: none; display: flex; gap: 4px; } .nav-links a { color: #cbd5e1; text-decoration: none; font-size: 0.9rem; font-weight: 500; padding: 6px 14px; border-radius: 6px; transition: background 0.2s, color 0.2s; } .nav-links a:hover, .nav-links a.active { background: #2563eb; color: #ffffff; } /* ── Hamburger (hidden on desktop) ── */ .hamburger { display: none; flex-direction: column; gap: 5px; cursor: pointer; background: none; border: none; padding: 6px; } .hamburger span { display: block; width: 24px; height: 2px; background: #cbd5e1; border-radius: 2px; transition: all 0.3s ease; }
Making It Responsive with Media Queries
This is where the magic happens. Below 768px screen width, we hide the nav links and show the hamburger button instead. When clicked, JavaScript will toggle a class to show/hide the menu.
/* ── Mobile Styles ── */ @media (max-width: 768px) { .hamburger { display: flex; /* Show hamburger on mobile */ } .nav-links { display: none; /* Hide links by default */ position: absolute; top: 60px; left: 0; right: 0; background: #1e293b; flex-direction: column; padding: 12px 24px 20px; gap: 4px; border-top: 1px solid #334155; } .nav-links.open { display: flex; /* Show when JS adds .open class */ } .nav-links a { padding: 10px 12px; font-size: 0.95rem; } /* ── Hamburger → X Animation ── */ .hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); } .hamburger.open span:nth-child(2) { opacity: 0; } .hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } }
Remember: The .navbar must have position: sticky or position: relative for the mobile dropdown to position correctly using position: absolute.
JavaScript for the Hamburger Menu
Now create a file called script.js. This is a very small script — only 10 lines — that toggles the .open class on the hamburger button and nav links when the button is clicked.
// Select the hamburger button and nav links const hamburger = document.getElementById('hamburger'); const navLinks = document.getElementById('navLinks'); // Toggle menu open/closed on button click hamburger.addEventListener('click', () => { hamburger.classList.toggle('open'); navLinks.classList.toggle('open'); }); // Close menu when a nav link is clicked (good for single-page sites) navLinks.querySelectorAll('a').forEach(link => { link.addEventListener('click', () => { hamburger.classList.remove('open'); navLinks.classList.remove('open'); }); });
That's it! Three files — index.html, style.css, script.js — and you have a fully working responsive navbar.
Live Demo Preview
Here's how your navbar will look. Try resizing your browser window to see it go mobile:
Bonus: Active Link Highlight with JavaScript
Want the current page link to always be highlighted? Add this snippet to your script.js — it automatically adds the .active class to whichever link matches the current page URL.
// Auto-highlight the active nav link based on current page const currentPage = window.location.href; document.querySelectorAll('.nav-links a').forEach(link => { if (currentPage.includes(link.getAttribute('href'))) { link.classList.add('active'); } });
Complete Final Code (All-in-One)
If you prefer a single file instead of three separate files, here's the complete self-contained version:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Responsive Navbar</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: sans-serif; } .navbar { background: #1e293b; position: sticky; top: 0; z-index: 1000; } .nav-container { max-width: 1100px; margin: 0 auto; padding: 0 24px; height: 60px; display: flex; align-items: center; justify-content: space-between; } .nav-logo { color: #fff; font-size: 1.3rem; font-weight: 700; text-decoration: none; } .nav-links { list-style: none; display: flex; gap: 4px; } .nav-links a { color: #cbd5e1; text-decoration: none; font-size: 0.9rem; font-weight: 500; padding: 6px 14px; border-radius: 6px; transition: background 0.2s, color 0.2s; } .nav-links a:hover, .nav-links a.active { background: #2563eb; color: #fff; } .hamburger { display: none; flex-direction: column; gap: 5px; cursor: pointer; background: none; border: none; padding: 6px; } .hamburger span { display: block; width: 24px; height: 2px; background: #cbd5e1; border-radius: 2px; transition: all 0.3s ease; } @media (max-width: 768px) { .hamburger { display: flex; } .nav-links { display: none; position: absolute; top: 60px; left: 0; right: 0; background: #1e293b; flex-direction: column; padding: 12px 24px 20px; gap: 4px; border-top: 1px solid #334155; } .nav-links.open { display: flex; } .nav-links a { padding: 10px 12px; font-size: 0.95rem; } .hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); } .hamburger.open span:nth-child(2) { opacity: 0; } .hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } } </style> </head> <body> <nav class="navbar"> <div class="nav-container"> <a href="#" class="nav-logo">GrowWP</a> <ul class="nav-links" id="navLinks"> <li><a href="#" class="active">Home</a></li> <li><a href="#">Blogs</a></li> <li><a href="#">Tools</a></li> <li><a href="#">About</a></li> <li><a href="#">Contact</a></li> </ul> <button class="hamburger" id="hamburger" aria-label="Toggle menu"> <span></span><span></span><span></span> </button> </div> </nav> <script> const hamburger = document.getElementById('hamburger'); const navLinks = document.getElementById('navLinks'); hamburger.addEventListener('click', () => { hamburger.classList.toggle('open'); navLinks.classList.toggle('open'); }); navLinks.querySelectorAll('a').forEach(link => { link.addEventListener('click', () => { hamburger.classList.remove('open'); navLinks.classList.remove('open'); }); }); </script> </body> </html>
Conclusion
Congratulations! 🎉 You just built a fully responsive navigation bar from scratch using only HTML, CSS, and JavaScript — no frameworks, no external libraries.
Here's a quick recap of what you learned:
- How to use the semantic
<nav>tag - How to style a desktop navbar with Flexbox
- How to use CSS Media Queries to make it mobile-friendly
- How to build a hamburger menu animation with pure CSS
- How to use JavaScript classList.toggle() to open/close the menu
These are foundational skills every web developer should know. Once you're comfortable here, you can take this further with dropdown menus, sticky scroll effects, or even integrating this into your WordPress theme's header.php.
Next Step: Try adding a dropdown submenu to one of the nav links. It's the natural next challenge after mastering this! Check GrowWP's upcoming tutorial on CSS Dropdowns.
📥 Want More Free Web Dev Guides?
Download our free WordPress + Web Development PDF cheatsheets — no signup needed.
Get Free PDFs →