导航栏是几乎所有网站都必备的组件,一个好的响应式导航栏需要在不同设备上都能提供出色的用户体验。本节将介绍如何使用 Tailwind CSS 实现功能完善的响应式导航栏。
基础导航栏结构
桌面端导航
<nav class="bg-white shadow"><div class="max-w-7xl mx-auto px-4"><div class="flex justify-between h-16"><!-- Logo --><div class="flex-shrink-0 flex items-center"><img class="h-8 w-auto" src="/logo.svg" alt="Logo" /></div><!-- 主导航菜单 --><div class="hidden md:flex items-center space-x-8"><a href="/" class="text-gray-900 hover:text-gray-600 px-3 py-2 text-sm font-medium">首页</a><a href="/products" class="text-gray-900 hover:text-gray-600 px-3 py-2 text-sm font-medium">产品</a><a href="/about" class="text-gray-900 hover:text-gray-600 px-3 py-2 text-sm font-medium">关于</a><a href="/contact" class="text-gray-900 hover:text-gray-600 px-3 py-2 text-sm font-medium">联系我们</a></div><!-- 用户菜单 --><div class="hidden md:flex items-center space-x-4"><button class="bg-gray-100 hover:bg-gray-200 px-4 py-2 rounded-lg text-sm font-medium">登录</button><button class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium">注册</button></div></div></div></nav>
移动端菜单按钮
<!-- 汉堡菜单按钮 --><div class="flex md:hidden"><button type="button"class="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-gray-900 hover:bg-gray-100"aria-controls="mobile-menu"aria-expanded="false"><span class="sr-only">打开主菜单</span><!-- 汉堡菜单图标 --><svg 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><!-- 关闭图标 --><svg 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 class="md:hidden" id="mobile-menu"><div class="px-2 pt-2 pb-3 space-y-1"><a href="/" class="block px-3 py-2 rounded-md text-base font-medium text-gray-900 hover:bg-gray-100">首页</a><a href="/products" class="block px-3 py-2 rounded-md text-base font-medium text-gray-900 hover:bg-gray-100">产品</a><a href="/about" class="block px-3 py-2 rounded-md text-base font-medium text-gray-900 hover:bg-gray-100">关于</a><a href="/contact" class="block px-3 py-2 rounded-md text-base font-medium text-gray-900 hover:bg-gray-100">联系我们</a></div><div class="pt-4 pb-3 border-t border-gray-200"><div class="px-2 space-y-1"><button class="block w-full text-left px-3 py-2 rounded-md text-base font-medium text-gray-900 hover:bg-gray-100">登录</button><button class="block w-full text-left px-3 py-2 rounded-md text-base font-medium bg-blue-500 text-white hover:bg-blue-600">注册</button></div></div></div>
交互功能实现
菜单切换功能
function setupMobileMenu() {const button = document.querySelector('[aria-controls="mobile-menu"]')const menu = document.getElementById('mobile-menu')const icons = button.querySelectorAll('svg')button.addEventListener('click', () => {const expanded = button.getAttribute('aria-expanded') === 'true'button.setAttribute('aria-expanded', !expanded)menu.classList.toggle('hidden')icons[0].classList.toggle('hidden')icons[1].classList.toggle('hidden')})}
滚动处理
function handleNavbarScroll() {const navbar = document.querySelector('nav')let lastScroll = 0window.addEventListener('scroll', () => {const currentScroll = window.pageYOffsetif (currentScroll <= 0) {navbar.classList.remove('-translate-y-full')return}if (currentScroll > lastScroll && !navbar.contains(document.activeElement)) {// 向下滚动时隐藏navbar.classList.add('-translate-y-full')} else {// 向上滚动时显示navbar.classList.remove('-translate-y-full')}lastScroll = currentScroll})}
高级功能实现
下拉菜单
<div class="relative group"><button class="flex items-center space-x-1 text-gray-900 hover:text-gray-600 px-3 py-2 text-sm font-medium"><span>产品</span><svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" /></svg></button><div class="absolute left-0 w-48 mt-2 bg-white rounded-lg shadow-lg py-2 hidden group-hover:block"><a href="/products/category1" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">分类一</a><a href="/products/category2" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">分类二</a><a href="/products/category3" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">分类三</a></div></div>
搜索框集成
<div class="flex-1 flex justify-center px-2 lg:ml-6 lg:justify-end"><div class="max-w-lg w-full lg:max-w-xs"><label for="search" class="sr-only">搜索</label><div class="relative"><div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"><svg class="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg></div><input id="search"type="search"class="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-blue-500 focus:border-blue-500 sm:text-sm"placeholder="搜索" /></div></div></div>
样式优化
活跃状态
<a href="/products"class="text-gray-900 hover:text-gray-600 px-3 py-2 text-sm font-mediumborder-b-2 border-transparent hover:border-gray-300transition-colors duration-200aria-[current=page]:text-blue-600 aria-[current=page]:border-blue-600"aria-current="page">产品</a>
滚动动效
<nav class="fixed top-0 inset-x-0 bg-white shadowtransform transition-transform duration-300motion-reduce:transition-none"><!-- 导航内容 --></nav>
深色模式支持
<nav class="bg-white dark:bg-gray-800 shadow"><div class="max-w-7xl mx-auto px-4"><div class="flex justify-between h-16"><!-- Logo --><div class="flex-shrink-0 flex items-center"><img class="h-8 w-auto block dark:hidden" src="/logo-light.svg" alt="Logo" /><img class="h-8 w-auto hidden dark:block" src="/logo-dark.svg" alt="Logo" /></div><!-- 导航链接 --><div class="hidden md:flex items-center space-x-8"><a href="/" class="text-gray-900 dark:text-gray-100 hover:text-gray-600 dark:hover:text-gray-300">首页</a><!-- 更多链接 --></div></div></div></nav>
性能优化
延迟加载
// 延迟加载非关键资源function lazyLoadNavResources() {const images = document.querySelectorAll('nav img[data-src]')const observer = new IntersectionObserver((entries) => {entries.forEach(entry => {if (entry.isIntersecting) {const img = entry.targetimg.src = img.dataset.srcobserver.unobserve(img)}})})images.forEach(img => observer.observe(img))}
动画性能
/* 使用 transform 而不是 margin/top 来实现动画 */.nav-animation {transform: translateY(0);transition: transform 0.3s ease;will-change: transform;}.nav-hidden {transform: translateY(-100%);}
可访问性增强
键盘导航
function setupKeyboardNav() {const menuItems = document.querySelectorAll('nav a, nav button')menuItems.forEach((item, index) => {item.addEventListener('keydown', (e) => {switch (e.key) {case 'ArrowRight':e.preventDefault()menuItems[(index + 1) % menuItems.length].focus()breakcase 'ArrowLeft':e.preventDefault()menuItems[(index - 1 + menuItems.length) % menuItems.length].focus()break}})})}
ARIA 属性支持
<nav role="navigation" aria-label="主导航"><button type="button"aria-controls="mobile-menu"aria-expanded="false"aria-label="打开主菜单"><!-- 按钮内容 --></button><div id="mobile-menu"role="menu"aria-orientation="vertical"aria-labelledby="menu-button"><!-- 菜单内容 --></div></nav>
最佳实践
响应式设计原则
- 移动优先设计
- 断点设置合理
- 内容优先级排序
交互设计要点
- 清晰的视觉反馈
- 平滑的动画过渡
- 直观的操作方式
性能优化策略
- 合理使用 CSS transforms
- 避免布局抖动
- 资源按需加载
可访问性建议
- 完善的键盘支持
- 适当的 ARIA 属性
- 合理的颜色对比度
