如何为适配移动端的Navbar创建可用的下拉菜单
问题背景
现有基于HTML/CSS/JS的移动端Navbar,汉堡菜单点击带动画效果,需为「Products」导航项添加适配移动端的下拉菜单。
修改后的完整代码
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>NavBar</title> <link rel="stylesheet" href="style2.css"> <script defer src="script2.js"></script> </head> <body> <div class="root"> <header class="header"> <div class="navbar"> <div class="navbar-content"> <a href="#" class="logo"> <img src="media/insert logo img here" alt="Logo" class="logo-img"> </a> <nav class="nav"> <ul class="nav-list"> <li class="nav-item"> <a href="#" class="nav-link">Home</a> </li> <li class="nav-item dropdown"> <a href="#" class="nav-link dropbtn">Products</a> <div class="dropdown-content"> <a href="#" class="nav-link">Dropdown one</a> <a href="#" class="nav-link">Dropdown two</a> </div> </li> <li class="nav-item"> <a href="#" class="nav-link">About</a> </li> <li class="nav-item"> <a href="#" class="nav-link">Contact</a> </li> </ul> </nav> <div class="hamburger"> <div class="bar"></div> <div class="bar"></div> <div class="bar"></div> </div> </div> </div> </header> </div> </body> </html>
CSS
/* RESET */ * { margin: 0; padding: 0; box-sizing: border-box; } ul { list-style: none; } a { text-decoration: none; color: inherit; } /* BASE STYLE */ body { background-color: #e8f0f7; font-family: 'Inter', sans-serif; min-height: 500vh; } /* NORMAL STYLES */ .header { position: fixed; width: 100%; } .navbar { background-color: rgb(19, 22, 26); } .navbar-content { min-height: 60px; max-width: 1200px; padding: 0 30px; margin: 0 auto; display: flex; justify-content: space-between; align-items: center; } .logo { vertical-align: middle; display: flex; column-gap: 10px; align-items: center; } .logo-img { height: 30px; } .logo-text { font-size: 20px; color: #fff; font-weight: 500; letter-spacing: -0.5px; } .nav { transition: all 0.3s ease-in-out; } .nav-list { display: flex; column-gap: 40px; } .nav-link{ color: rgba(255, 255, 255, 0.75); transition: all 0.2s; } .nav-link:hover, .nav-link:focus { color: rgba(255, 255, 255, 1); } .hamburger { cursor: pointer; display: none; } .bar { height: 2px; width: 27px; background-color: #fff; margin: 5px 0; opacity: 0.8; transition: all 0.3s ease-in-out; } /* 下拉菜单基础样式 */ .dropdown { position: relative; } .dropdown-content { display: none; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); background-color: rgb(19, 22, 26); border-radius: 4px; padding: 10px 0; min-width: 150px; text-align: center; } /* 桌面端hover显示下拉 */ .dropdown:hover .dropdown-content { display: block; } /* For JS */ .nav-open { left: 50% !important; } .hamburger-open .bar:nth-child(1) { transform: translateY(7px) rotate(45deg); } .hamburger-open .bar:nth-child(2) { transform: translateY(7px) rotate(45deg); opacity: 0; } .hamburger-open .bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } /* 移动端下拉菜单激活样式 */ .dropdown-active .dropdown-content { display: block; } /* MEDIA QUERIES */ @media (max-width: 650px) { .nav { position: fixed; top: 60px; left: -100%; transform: translateX(-50%); background-color: rgb(19, 22, 26); width: 100%; padding: 10px 0 25px; } .nav-list { flex-direction: column; align-items: center; row-gap: 20px; } .nav-link { font-size: 14px; } .hamburger { display: block; } /* 移动端下拉菜单调整 */ .dropdown-content { position: static; transform: none; margin-top: 15px; padding-top: 15px; border-top: 1px solid rgba(255,255,255,0.1); row-gap: 10px; display: flex; flex-direction: column; } } @media (max-width: 360px) { .top-bar__content { font-size: 10px; } }
JavaScript
const navEl = document.querySelector('.nav'); const hamburgerEl = document.querySelector('.hamburger'); const navItemsEls = document.querySelectorAll('.nav-item'); const dropdownEl = document.querySelector('.dropdown'); hamburgerEl.addEventListener('click', () => { navEl.classList.toggle('nav-open'); hamburgerEl.classList.toggle('hamburger-open'); }); navItemsEls.forEach(navItemEl => { navItemEl.addEventListener('click', (e) => { // 普通导航项点击关闭导航栏,下拉项仅切换菜单状态 if (!navItemEl.classList.contains('dropdown')) { navEl.classList.remove('nav-open'); hamburgerEl.classList.remove('hamburger-open'); } else { e.stopPropagation(); dropdownEl.classList.toggle('dropdown-active'); } }); }); // 点击页面其他区域关闭导航栏和下拉菜单 document.addEventListener('click', (e) => { if (!navEl.contains(e.target) && !hamburgerEl.contains(e.target)) { navEl.classList.remove('nav-open'); hamburgerEl.classList.remove('hamburger-open'); dropdownEl.classList.remove('dropdown-active'); } });
关键修改说明
- HTML修正:修复「Contact」项的类名错误(
nav-tem改为nav-item),确保选择器正常生效 - CSS新增:
- 桌面端hover触发下拉的基础样式
- 移动端下拉菜单改为静态布局,添加分隔线增强视觉层级
- 新增
dropdown-active类控制移动端下拉菜单的显示/隐藏
- JS逻辑优化:
- 区分普通导航项和下拉项的点击行为,避免下拉菜单触发导航栏关闭
- 点击页面空白区域时,同步关闭导航栏和下拉菜单
- 阻止下拉项点击事件冒泡,保证交互逻辑独立
内容的提问来源于stack exchange,提问作者Ackersand
相关产品推荐
相关产品推荐

