必须用transform: translateX()而非left/top,因其触发GPU加速、避免重排卡顿;初始设translateX(-100%)、visibility:hidden、opacity:0,开启动画时切至translateX(0)、visible、opacity:1,并配精准transition声明。

Drawer动画必须用transform而不是left/top
直接改left或top会触发重排,动画卡顿明显,尤其在移动端。浏览器对transform: translateX()有硬件加速支持,滑动顺滑得多。
常见错误是用display: none配合transition——这根本不会动画,因为display不可过渡。正确做法是用visibility + transform + opacity三者协同控制显隐和动效。
- 初始状态设
transform: translateX(-100%)(完全左移出屏) - 打开时改为
transform: translateX(0),同时visibility: visible、opacity: 1 - 关闭时反向设置,并加
transition: transform 0.3s ease, opacity 0.2s ease
如何用CSS类控制Drawer开关状态
不推荐用JS反复操作style属性,应通过切换class来触发CSS动画。核心是两个类:drawer-open表示展开,drawer-closed表示收起(或只用一个is-open布尔类)。
示例结构:
立即学习“前端免费学习笔记(深入)”;
.drawer {
position: fixed;
top: 0;
left: 0;
width: 280px;
height: 100%;
background: #fff;
transform: translateX(-100%);
visibility: hidden;
opacity: 0;
transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.2s ease;
}
.drawer.is-open {
transform: translateX(0);
visibility: visible;
opacity: 1;
}
JS只需element.classList.toggle('is-open')即可,无需手动控制timing或状态。
遮罩层Backdrop怎么同步淡入并阻止背景滚动
Drawer常带半透明遮罩,它不仅要淡入,还得挡住背后页面滚动。关键点有两个:
- 遮罩
backdrop需设position: fixed; z-index高于Drawer内容但低于Drawer本身 - 打开Drawer时,给
<body>加overflow: hidden,否则iOS Safari仍可滚动背景 - 遮罩的
transition建议用opacity而非visibility,避免点击穿透
注意:overflow: hidden加在body上后,页面会“跳一下”,因为滚动条消失导致宽度变化。可补一句body { padding-right: env(safe-area-inset-right) }或用margin-right补偿滚动条宽度。
移动端触摸拖拽Drawer需要额外处理
CSS原生动画只响应class切换,不支持手指拖拽。若要实现“拖动关闭”或“松手自动吸附”,必须用JS监听touchmove,实时更新transform: translateX()内联样式,并在touchend判断位移阈值决定是收起还是回弹。
此时CSS只需提供基础过渡(如transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1)),让JS控制的每一帧都能平滑插值。别忘了在拖拽中禁用body默认滚动:event.preventDefault()在touchmove里,且touch-action: none加在Drawer容器上防止误触发缩放。
这个交互层复杂度远超纯CSS动画,多数项目其实只需点击开关+滑入滑出就够了——先确保基础动效可靠,再考虑拖拽增强。


















