如何实现点击hamburger menu触发元素动效的animated navbar?
带动画效果的汉堡导航栏实现方案
核心逻辑不用依赖任何第三方动画库,原生HTML+CSS+JS就能实现:点击汉堡按钮时通过JS切换导航相关元素的状态类,所有动画效果全部用CSS过渡/关键帧实现,性能比纯JS写动画好很多。
1. 搭建基础HTML结构
结构尽量简单,分成logo、汉堡按钮、导航菜单三个核心部分即可,后续要加其他导航内元素直接往菜单容器里塞:
<nav class="navbar"> <div class="nav-logo">站点Logo</div> <button class="hamburger" aria-label="切换导航菜单"> <span class="bar"></span> <span class="bar"></span> <span class="bar"></span> </button> <ul class="nav-menu"> <li class="nav-item"><a href="#" class="nav-link">首页</a></li> <li class="nav-item"><a href="#" class="nav-link">产品功能</a></li> <li class="nav-item"><a href="#" class="nav-link">关于我们</a></li> <li class="nav-item"><a href="#" class="nav-link">联系方式</a></li> </ul> </nav>
2. 编写CSS样式和动画规则
核心要做三层动画,所有动画都靠transition实现,不需要写复杂关键帧:
- 汉堡按钮的三条横线:点击后从汉堡形态平滑变成叉号
- 导航菜单容器:移动端默认隐藏在视口外,点击后平滑滑入
- 菜单内的子元素:默认透明度0、位置偏移,菜单激活后按顺序错开时间淡入归位,做出错落的入场效果
对应代码如下:
* { margin: 0; padding: 0; box-sizing: border-box; list-style: none; text-decoration: none; } .navbar { position: fixed; top: 0; width: 100%; padding: 1rem 5%; display: flex; justify-content: space-between; align-items: center; background: #ffffff; box-shadow: 0 2px 12px rgba(0,0,0,0.08); z-index: 999; } .hamburger { display: none; border: none; background: transparent; cursor: pointer; padding: 4px; } .bar { display: block; width: 24px; height: 3px; margin: 5px 0; background-color: #1f2937; transition: all 0.3s ease; border-radius: 2px; } .nav-menu { display: flex; gap: 2.5rem; align-items: center; } .nav-link { font-size: 1rem; color: #1f2937; transition: color 0.2s ease; } .nav-link:hover { color: #2563eb; } /* 移动端适配逻辑 */ @media (max-width: 768px) { .hamburger { display: block; } /* 汉堡按钮激活态:转成叉号 */ .hamburger.active .bar:nth-child(2) { opacity: 0; } .hamburger.active .bar:nth-child(1) { transform: translateY(8px) rotate(45deg); } .hamburger.active .bar:nth-child(3) { transform: translateY(-8px) rotate(-45deg); } /* 菜单默认收起状态 */ .nav-menu { position: fixed; left: -100%; top: 66px; flex-direction: column; gap: 0; width: 100%; background: #ffffff; text-align: center; transition: left 0.3s ease; box-shadow: 0 8px 10px rgba(0,0,0,0.05); padding: 1rem 0; } /* 菜单激活态:滑入视口 */ .nav-menu.active { left: 0; } /* 导航项默认状态:偏移+透明 */ .nav-item { margin: 1rem 0; opacity: 0; transform: translateY(15px); transition: all 0.3s ease; } /* 激活态下逐个加延迟,做错落入场 */ .nav-menu.active .nav-item:nth-child(1) { transition-delay: 0.2s; opacity: 1; transform: translateY(0); } .nav-menu.active .nav-item:nth-child(2) { transition-delay: 0.28s; opacity: 1; transform: translateY(0); } .nav-menu.active .nav-item:nth-child(3) { transition-delay: 0.36s; opacity: 1; transform: translateY(0); } .nav-menu.active .nav-item:nth-child(4) { transition-delay: 0.44s; opacity: 1; transform: translateY(0); } }
3. 添加少量JS做状态切换
逻辑非常简单,只需要监听点击事件切换类名就行,额外加个点击导航链接自动收起菜单的逻辑,体验更好:
const hamburger = document.querySelector('.hamburger'); const navMenu = document.querySelector('.nav-menu'); const navLinks = document.querySelectorAll('.nav-link'); // 点击汉堡按钮切换菜单状态 hamburger.addEventListener('click', () => { hamburger.classList.toggle('active'); navMenu.classList.toggle('active'); }); // 点击任意导航链接后自动收起菜单 navLinks.forEach(link => { link.addEventListener('click', () => { hamburger.classList.remove('active'); navMenu.classList.remove('active'); }) });
自定义调整提示
- 想要弹性动效可以把过渡的
ease换成cubic-bezier(0.34, 1.56, 0.64, 1),注意不要把动画时长设太长,0.3-0.5s是比较舒服的区间 - 新增导航内元素(比如登录按钮、搜索框)的时候,照着
.nav-item的写法给元素加默认的偏移/透明状态,在.nav-menu.active选择器下设置激活状态,加对应延迟就能跟着整体一起做入场动画 - 菜单的入场方向可以自己改,比如要从上往下滑就把
left:-100%改成top: -100%,激活态设top:66px就行
内容的提问来源于stack exchange,提问作者Tanjim Hasan
相关产品推荐
相关产品推荐

