Building Navigation & Header Components
Building Navigation & Header Components
Learn how to build professional, responsive navigation components from scratch using Tailwind CSS. Master mobile menus, dropdowns, sticky headers, and accessibility best practices.
Basic Navbar Structure
Start with a semantic HTML structure for your navigation:
Simple Navbar HTML
<nav class="bg-white shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<!-- Logo -->
<div class="flex items-center">
<a href="/" class="flex-shrink-0 flex items-center">
<img class="h-8 w-auto" src="/logo.svg" alt="Logo">
</a>
</div>
<!-- Desktop Navigation -->
<div class="hidden md:flex md:items-center md:space-x-8">
<a href="/about" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
About
</a>
<a href="/services" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
Services
</a>
<a href="/contact" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
Contact
</a>
</div>
<!-- Mobile menu button -->
<div class="md:hidden flex items-center">
<button type="button" class="text-gray-700 hover:text-blue-600">
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
</div>
</div>
</nav>
<nav> for navigation landmarks, <a> for links, and <button> for interactive elements. This improves accessibility and SEO.
Responsive Mobile Menu
Create a mobile menu that toggles visibility with JavaScript:
Full Navbar with Mobile Menu
<nav class="bg-white shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<a href="/" class="flex-shrink-0">
<img class="h-8 w-auto" src="/logo.svg" alt="Logo">
</a>
</div>
<!-- Desktop menu -->
<div class="hidden md:flex md:items-center md:space-x-4">
<a href="/" class="text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
Home
</a>
<a href="/about" class="text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
About
</a>
<a href="/services" class="text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-sm font-medium transition-colors">
Services
</a>
<a href="/contact" class="bg-blue-600 text-white hover:bg-blue-700 px-4 py-2 rounded-md text-sm font-medium transition-colors">
Contact Us
</a>
</div>
<!-- Mobile menu button -->
<div class="md:hidden flex items-center">
<button
id="mobile-menu-button"
type="button"
class="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-blue-600 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500"
aria-expanded="false"
aria-controls="mobile-menu"
>
<span class="sr-only">Open main menu</span>
<!-- Hamburger icon -->
<svg id="menu-open-icon" class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<!-- Close icon -->
<svg id="menu-close-icon" class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
<!-- Mobile menu panel -->
<div id="mobile-menu" class="hidden md:hidden">
<div class="px-2 pt-2 pb-3 space-y-1">
<a href="/" class="block text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-base font-medium">
Home
</a>
<a href="/about" class="block text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-base font-medium">
About
</a>
<a href="/services" class="block text-gray-700 hover:text-blue-600 hover:bg-blue-50 px-3 py-2 rounded-md text-base font-medium">
Services
</a>
<a href="/contact" class="block bg-blue-600 text-white hover:bg-blue-700 px-3 py-2 rounded-md text-base font-medium">
Contact Us
</a>
</div>
</div>
</nav>
<script>
const menuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
const openIcon = document.getElementById('menu-open-icon');
const closeIcon = document.getElementById('menu-close-icon');
menuButton.addEventListener('click', () => {
const isOpen = mobileMenu.classList.contains('hidden');
mobileMenu.classList.toggle('hidden');
openIcon.classList.toggle('hidden');
closeIcon.classList.toggle('hidden');
menuButton.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
});
</script>
transition-all duration-300 ease-in-out to the mobile menu for smooth opening/closing animations. You can also use max-h-0 to max-h-screen transitions instead of hidden.
Sticky Navigation Header
Create a navigation bar that sticks to the top when scrolling:
Sticky Navbar with Scroll Effects
<nav id="navbar" class="sticky top-0 z-50 bg-white shadow-md transition-all duration-300">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center">
<a href="/" class="font-bold text-xl text-blue-600">
Brand
</a>
</div>
<div class="flex items-center space-x-4">
<a href="#home" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">Home</a>
<a href="#about" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">About</a>
<a href="#services" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">Services</a>
<a href="#contact" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">Contact</a>
</div>
</div>
</div>
</nav>
<script>
const navbar = document.getElementById('navbar');
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
// Add shadow and reduce height when scrolled
navbar.classList.add('shadow-lg');
navbar.querySelector('div').classList.remove('h-16');
navbar.querySelector('div').classList.add('h-14');
} else {
// Reset to original state
navbar.classList.remove('shadow-lg');
navbar.querySelector('div').classList.remove('h-14');
navbar.querySelector('div').classList.add('h-16');
}
lastScroll = currentScroll;
});
</script>
Dropdown Menus
Build accessible dropdown menus for navigation items with sub-items:
Navbar with Dropdown
<nav class="bg-white shadow-lg">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16">
<div class="flex items-center space-x-8">
<a href="/" class="font-bold text-xl text-blue-600">Brand</a>
<a href="/about" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
About
</a>
<!-- Dropdown -->
<div class="relative group">
<button class="flex items-center text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium group">
Services
<svg class="ml-1 h-4 w-4 transition-transform group-hover:rotate-180" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<!-- Dropdown menu -->
<div class="absolute left-0 mt-2 w-48 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 transform group-hover:translate-y-0 -translate-y-2">
<div class="bg-white rounded-lg shadow-xl ring-1 ring-black ring-opacity-5 py-1">
<a href="/web-design" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
Web Design
</a>
<a href="/web-development" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
Web Development
</a>
<a href="/seo" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
SEO Services
</a>
<a href="/hosting" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">
Hosting
</a>
</div>
</div>
</div>
<a href="/contact" class="text-gray-700 hover:text-blue-600 px-3 py-2 text-sm font-medium">
Contact
</a>
</div>
</div>
</div>
</nav>
group-hover pattern works well on desktop but not on mobile. For production, use JavaScript to toggle dropdowns on click for mobile devices, and keep hover behavior for desktop.
Active Link Styling
Highlight the current page in navigation:
Active State Implementation
<!-- HTML with active classes -->
<nav class="bg-white shadow-lg">
<div class="max-w-7xl mx-auto px-4">
<div class="flex space-x-4">
<a
href="/"
class="px-3 py-2 text-sm font-medium rounded-md
text-blue-600 bg-blue-50 border-b-2 border-blue-600"
aria-current="page"
>
Home
</a>
<a
href="/about"
class="px-3 py-2 text-sm font-medium rounded-md
text-gray-700 hover:text-blue-600 hover:bg-blue-50"
>
About
</a>
<a
href="/services"
class="px-3 py-2 text-sm font-medium rounded-md
text-gray-700 hover:text-blue-600 hover:bg-blue-50"
>
Services
</a>
</div>
</div>
</nav>
<!-- JavaScript to set active link -->
<script>
// Get current page path
const currentPath = window.location.pathname;
// Find all nav links
const navLinks = document.querySelectorAll('nav a');
navLinks.forEach(link => {
// Remove active classes from all links
link.classList.remove('text-blue-600', 'bg-blue-50', 'border-b-2', 'border-blue-600');
link.removeAttribute('aria-current');
// Add active classes to current page link
if (link.getAttribute('href') === currentPath) {
link.classList.add('text-blue-600', 'bg-blue-50', 'border-b-2', 'border-blue-600');
link.setAttribute('aria-current', 'page');
}
});
</script>
Breadcrumb Navigation
Create breadcrumbs to show page hierarchy:
Breadcrumb Component
<nav class="flex py-3 px-5 bg-gray-50 rounded-lg" aria-label="Breadcrumb">
<ol class="inline-flex items-center space-x-1 md:space-x-3">
<li class="inline-flex items-center">
<a href="/" class="inline-flex items-center text-sm font-medium text-gray-700 hover:text-blue-600">
<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path>
</svg>
Home
</a>
</li>
<li>
<div class="flex items-center">
<svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
</svg>
<a href="/products" class="ml-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ml-2">
Products
</a>
</div>
</li>
<li aria-current="page">
<div class="flex items-center">
<svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
</svg>
<span class="ml-1 text-sm font-medium text-gray-500 md:ml-2">
Laptops
</span>
</div>
</li>
</ol>
</nav>
Mega Menu Pattern
Build a large dropdown menu with multiple columns:
Mega Menu Navigation
<nav class="bg-white shadow-lg">
<div class="max-w-7xl mx-auto px-4">
<div class="flex justify-between h-16">
<div class="flex items-center space-x-8">
<a href="/" class="font-bold text-xl">Brand</a>
<!-- Mega menu trigger -->
<div class="relative group">
<button class="flex items-center px-3 py-2 text-sm font-medium text-gray-700 hover:text-blue-600">
Products
<svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<!-- Mega menu panel -->
<div class="absolute left-0 w-screen max-w-7xl opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
<div class="mt-2 bg-white rounded-lg shadow-2xl ring-1 ring-black ring-opacity-5">
<div class="grid grid-cols-4 gap-8 p-8">
<!-- Column 1 -->
<div>
<h3 class="text-sm font-semibold text-gray-900 uppercase tracking-wider mb-4">
Electronics
</h3>
<ul class="space-y-3">
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Smartphones</a>
</li>
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Laptops</a>
</li>
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Tablets</a>
</li>
</ul>
</div>
<!-- Column 2 -->
<div>
<h3 class="text-sm font-semibold text-gray-900 uppercase tracking-wider mb-4">
Fashion
</h3>
<ul class="space-y-3">
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Men's Clothing</a>
</li>
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Women's Clothing</a>
</li>
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Accessories</a>
</li>
</ul>
</div>
<!-- Column 3 -->
<div>
<h3 class="text-sm font-semibold text-gray-900 uppercase tracking-wider mb-4">
Home & Living
</h3>
<ul class="space-y-3">
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Furniture</a>
</li>
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Decor</a>
</li>
<li>
<a href="#" class="text-sm text-gray-700 hover:text-blue-600">Kitchen</a>
</li>
</ul>
</div>
<!-- Column 4 with image -->
<div class="bg-blue-50 rounded-lg p-6">
<h3 class="text-sm font-semibold text-gray-900 mb-2">
New Arrivals
</h3>
<p class="text-sm text-gray-600 mb-4">
Check out our latest products
</p>
<a href="#" class="inline-flex items-center text-sm font-medium text-blue-600 hover:text-blue-700">
Shop Now
<svg class="ml-1 w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
</svg>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</nav>
left-0 or left-1/2 -translate-x-1/2 to center mega menus. Be careful with w-screen on mega menus - it can cause horizontal scrolling. Consider using max-w-7xl or similar constraints.
Accessibility (ARIA) Best Practices
Make your navigation accessible to screen readers and keyboard users:
Accessible Navigation Example
<nav aria-label="Main navigation" class="bg-white shadow-lg">
<div class="max-w-7xl mx-auto px-4">
<div class="flex justify-between h-16">
<!-- Logo -->
<div class="flex items-center">
<a href="/" aria-label="Homepage">
<img src="/logo.svg" alt="Company Logo" class="h-8">
</a>
</div>
<!-- Navigation links -->
<ul class="flex items-center space-x-4" role="menubar">
<li role="none">
<a
href="/"
role="menuitem"
class="text-gray-700 hover:text-blue-600 px-3 py-2"
aria-current="page"
>
Home
</a>
</li>
<li role="none">
<a
href="/about"
role="menuitem"
class="text-gray-700 hover:text-blue-600 px-3 py-2"
>
About
</a>
</li>
<!-- Dropdown with ARIA -->
<li role="none" class="relative">
<button
id="services-button"
role="menuitem"
aria-haspopup="true"
aria-expanded="false"
aria-controls="services-menu"
class="flex items-center text-gray-700 hover:text-blue-600 px-3 py-2"
>
Services
<svg class="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<ul
id="services-menu"
role="menu"
aria-labelledby="services-button"
class="absolute left-0 mt-2 w-48 bg-white rounded-lg shadow-xl hidden"
>
<li role="none">
<a href="/web-design" role="menuitem" class="block px-4 py-2 text-sm hover:bg-blue-50">
Web Design
</a>
</li>
<li role="none">
<a href="/web-dev" role="menuitem" class="block px-4 py-2 text-sm hover:bg-blue-50">
Web Development
</a>
</li>
</ul>
</li>
</ul>
<!-- Mobile menu button with ARIA -->
<button
type="button"
aria-label="Toggle navigation menu"
aria-expanded="false"
aria-controls="mobile-menu"
class="md:hidden"
>
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
</div>
</nav>
tabindex="0" to focusable elements and implement keyboard event listeners for proper accessibility.
Exercise 1: Responsive Navbar
Build a complete responsive navigation component:
- Logo on the left
- 4-5 navigation links (desktop horizontal, mobile vertical)
- Hamburger menu for mobile (with smooth transition)
- CTA button (e.g., "Get Started")
- Active page highlighting
Exercise 2: Sticky Header with Effects
Create a sticky header that changes on scroll:
- Starts with larger height (h-20)
- Shrinks to smaller height (h-14) after scrolling 100px
- Background changes from transparent to solid white
- Shadow increases on scroll
- Smooth transitions for all changes
Exercise 3: Accessible Mega Menu
Build an accessible mega menu navigation:
- 3-4 main navigation items
- One item opens a mega menu with 3 columns
- Include icons or images in mega menu
- Proper ARIA attributes for screen readers
- Keyboard navigation support (Tab, Enter, Escape)
- Works on both hover (desktop) and click (mobile)