grid-template-columns 不能直接实现左右滑动抽屉效果,因其列宽属布局属性,无法平滑过渡,强行 transition 会触发重排卡顿甚至白屏;正确做法是用 Grid 划分结构、transform: translateX() 驱动动画。

不能用 grid-template-columns 直接做左右滑动抽屉——Grid 是布局系统,不是动画系统;滑动必须交由 transform: translateX() 驱动,Grid 只负责结构划分和响应式断点控制。
为什么 grid-template-columns 不能直接过渡出抽屉效果
Grid 的列宽(如 280px 1fr)属于布局属性,浏览器无法对它做平滑插值过渡。尝试写 transition: grid-template-columns 0.3s 会完全无效,或在部分浏览器中触发强制重排,导致卡顿甚至白屏。
-
grid-template-columns改变会触发 Layout + Paint,每帧都要重新计算所有子元素位置和尺寸 - 移动端尤其敏感,iOS Safari 会直接跳过过渡、表现为突变
- 即便配合
@media切换列数(如从280px 1fr→1fr),也只是“切换”,不是“滑动”
正确组合:Grid 布局 + transform 动画
把 Grid 当作“舞台”,把抽屉当作“演员”:Grid 定义主内容区与预留空间,抽屉用 position: fixed 脱离文档流,靠 transform: translateX() 滑入滑出。
- 主容器用
display: grid; grid-template-columns: 280px 1fr;,桌面端侧边栏常驻 - 移动端用
@media (max-width: 768px)改为grid-template-columns: 1fr;,隐藏侧边栏视觉占位 - 抽屉本身不参与 Grid 布局,而是作为
body的直接子元素,position: fixed; top: 0; left: 0; width: 280px; - 开关逻辑只操作抽屉的
transform: translateX(-100%)↔translateX(0)
左右双抽屉时的定位与 z-index 冲突
左抽屉用 left: 0 + translateX(-100%),右抽屉必须用 right: 0 + translateX(100%),否则两个抽屉会互相覆盖或错位。
- 右抽屉不能写
left: auto; right: 0; transform: translateX(100%);——100%仍按父容器宽度算,而父容器是body,宽度含滚动条,不可靠 - 统一改用
transform: translateX(100vw),确保完全滑出右侧视口 -
z-index必须分层:左抽屉z-index: 1000,右抽屉z-index: 1001,遮罩层z-index: 999,主内容z-index: 1 - 避免两个抽屉同时打开:JS 层需互斥控制,CSS 层加
pointer-events: none到非激活抽屉
移动端 touch 拖拽关闭时的常见失效点
用户手指横向拖拽抽屉关闭,但动画卡住或没响应——问题不在 CSS,而在事件监听配置错误。
-
touchstart里没调event.preventDefault(),iOS Safari 默认当页面滚动处理 -
touchmove监听器缺少{ passive: false },导致preventDefault()被忽略 - 位移计算用了
event.pageX,缩放或高 DPR 屏下不准;应改用event.touches[0].clientX - 松手后没判断拖动距离是否超过阈值(如
50px),导致轻微晃动就触发关闭
真正难的是状态同步:比如 Grid 断点切到移动端后,抽屉 DOM 仍存在但不可见,此时 JS 获取 getBoundingClientRect() 返回的 width 可能是 0,导致 translateX(-100%) 计算失准。别依赖实时尺寸,用 CSS 自定义属性(如 --drawer-width: 280px)固化关键数值更稳。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











