汉堡按钮(Hamburger menu)常用于移动端网站 展开/收起 导航,如果在点击按钮时再增加一些过渡动画则会显得更加生动有趣。今天我们就快速实现一个带有过渡动画的汉堡按钮。效果如图:
HTML
html 结构很简单,两个 div
足以:
<div class="menu">
<div class="hamburger"></div>
</div>
div.menu
代表按钮,div.hamburger
代表按钮中的线段。但是一个 div
如何显示 3 条线段?有同学应该想到了,可以用 ::before
、::after
伪元素。
CSS
为了让代码更简洁,选择使用 Sass 书写样式。
定义变量
首先我们需要定义一些变量,减少重复的参数。写样式的时候也可以像写组件那样去提炼配置,通过配置去修改、扩展。比如,线段的尺寸、位置都可以通过按钮尺寸 $menu-size
计算得到,这样一旦我们需要修改按钮尺寸就只需要修改 $menu-size
这一个参数就行了。
变量:
$menu-size: 300px; // 按钮尺寸
$line-width: $menu-size * 0.66; // 线段宽度
$line-height: $menu-size * 0.1; // 线段高度
$line-spacing: $menu-size * 0.22; // 线段间距
$line-color: #f44336; // 线段颜色
样式
按钮样式:
常规操作,没啥好讲的...
.menu {
// 水平、垂直居中
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
// 宽高
width: $menu-size;
height: $menu-size;
// 其他
cursor: pointer;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 6%;
}
线段样式:
.hamburger {
// 水平、垂直居中
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
// 线段样式
&,
&::before,
&::after {
content: "";
position: absolute;
width: $line-width;
height: $line-height;
background: $line-color;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
// 过渡时间
transition: 0.5s;
}
// 线段1位置
&::before {
top: -$line-spacing;
}
// 线段3位置
&::after {
top: $line-spacing;
}
}
注意点:
- 使用
transition
设置动画的过渡时间::before
、::after
伪元素是相对于div.hamburger
进行绝对定位(绝对定位的定义是:相对于最近的非static
定位的祖先元素的进行偏移。而不是 很多同学印象中的相对于position:relative
的祖先元素进行定位)
激活状态:
当点击按钮后通过 Javascript 给 div.menu
添加 active
的 class,表示按钮进入激活状态:
.menu.active {
.hamburger {
// 隐藏线段2
background-color: transparent;
box-shadow: none;
// 线段1 旋转定位
&::before {
top: 0;
transform: rotate(45deg);
}
// 线段3 旋转定位
&::after {
top: 0;
transform: rotate(135deg);
}
}
}
注意点:
- 隐藏线段 2 不能直接
display:none
或者visibility: hidden
,这样会导致使用伪元素实现的线段 1、3 都被隐藏,而是通过将背景色设置为透明实现- 给
::before
,::after
设置top: 0
相当于把线段 1、3 移到按钮中间,然后再进行旋转- 设置其他角度也可以达到最后变成 x 的效果,比如:
&::after {transform: rotate(-45deg)}
,只不过中间变换的过程会有所区别- 对中间变换过程有疑惑的同学建议将
transition
时间调长,仔细观察
JS
最后,监听按钮的点击事件,toggle 激活状态:
const menu = document.querySelector(".menu");
menu.addEventListener("click", () => {
menu.classList.toggle("active");
});
好了,大功告成!
本文 Demo 参考:Codepen Trick by Day (2020-07-07) Transforming Hamburger Menu
每天一个小技巧(Tricks by Day),量变引起质变,希望你和我一起每天多学一点,让技术有趣一点。所有示例将会汇总到我的 tricks-by-day github 项目中,欢迎大家莅临指导 😊
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。