三条需共用父容器并独立设置transform-origin: center和transition;菜单态平行居中,关闭态分别旋转±45°加位移、第二条透明隐藏,方能精准合成叉号。

用 transform 旋转三条线实现叉号过渡的关键点
直接上结论:三条 <span></span> 水平条必须共用同一父容器,且每条需独立设置 transform-origin 和 transition;否则旋转会错位或无动画。常见错误是只给父容器加 transition,结果线条飞出去或者不动。
核心逻辑是:菜单态三条线平行居中,关闭态第一条顺时针转 45°、第二条透明隐藏、第三条逆时针转 −45°,视觉合并成叉号。所有旋转必须围绕各自中心点,不能默认以左上角为原点。
- 每条线需设
display: block和固定宽高(如width: 24px; height: 2px) - 必须显式声明
transform-origin: center,否则rotate()会绕左上角转 -
transition要写在每条线的样式里,不是父容器上 - 第二条线不旋转,靠
opacity: 0隐藏,避免旋转后遮挡其他线
HTML 结构与基础 CSS 必须这样写
结构松散或层级嵌套过深会导致 transform 受父级 overflow 或 position 干扰。以下是最简可靠结构:
<button class="hamburger"> <span></span> <span></span> <span></span> </button>
对应 CSS 要强制重置默认行为:
- 父按钮设
position: relative,避免子元素transform脱离预期坐标系 - 每条
<span></span>设position: absolute+top: 50%+left: 50%+transform: translateY(-50%) translateX(-50%)居中(仅第一次定位,后续transform在此基础上叠加) - 三条线用
:nth-child(n)分别控制偏移:nth-child(1) { top: -6px; }、nth-child(2) { top: 0; }、nth-child(3) { top: 6px; }
触发叉号的 transform 组合必须分层控制
只靠 rotate() 不够,必须配合位移和透明度才能干净收口。点击切换时,激活类名(如 .is-active)要作用于父按钮,再通过后代选择器驱动子元素变化:
- 第一条线:
transform: rotate(45deg) translate(6px, 6px)(顺时针+右下微移,对齐叉号斜线) - 第二条线:
opacity: 0; transform: scale(0.5)(单纯隐藏,避免旋转后残留像素) - 第三条线:
transform: rotate(-45deg) translate(6px, -6px)(逆时针+右上微移) - 所有
transform动画需统一用transform 0.3s ease,不要拆成rotate和translate单独过渡
注意:Chrome 中若出现旋转抖动,大概率是未启用硬件加速,可加 transform: translateZ(0) 强制 GPU 渲染。
移动端点击区域小、动画卡顿的现实问题
真机上常遇到点击无响应或动画掉帧,根本原因不是 CSS 写错,而是触发时机和渲染压力:
- 务必给按钮加
touch-action: manipulation,否则 iOS Safari 会延迟 300ms 等待双击判断 - 避免在
:active状态里改transform,应由 JS 切换类名驱动,否则触摸反馈不及时 - 如果页面有大量
position: fixed元素,transform动画可能被降级为软件渲染,此时加will-change: transform仅对首帧有效,长期反而加重内存负担 - 安卓低端机上,三条线建议用
background-color而非border实现,后者在缩放时易糊边
真正难的不是写出叉号,而是让三根线在各种屏幕密度、不同内核下都稳稳地转进转出——细节都在 transform-origin、will-change 的取舍和硬件加速的实际生效条件里。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











