全屏侧拉抽屉菜单必须用visibility与transform配合,因visibility控制可访问性与焦点隔离但不触发动画,需显式声明transition时长;transform负责gpu加速位移且不触发重排,二者缺一不可,单独使用会导致卡顿、闪退或点击穿透。

全屏侧拉抽屉菜单不能靠 visibility 单独实现动画,必须和 transform 配合;否则会卡顿、闪退、或点击穿透——这是绝大多数人一开始就踩的坑。
为什么 visibility + translate 是最小可行组合
visibility: hidden 本身不触发动画,transition 对它无效,除非显式声明时长;而 transform: translateX() 负责位移,GPU 加速,不触发重排。两者分工明确:visibility 控制可访问性与焦点隔离,transform 负责视觉动效。
-
visibility: hidden关闭后,屏幕阅读器跳过、Tab 键无法进入,但元素仍占布局空间(这点反而利于遮罩层对齐) -
transform: translateX(-100%)把抽屉推离视口,但 DOM 仍在,不影响aria-hidden或focus()控制 - 必须同时设置
transition: visibility 0.3s, transform 0.3s,缺一不可;只写transition: all容易污染其他属性 - 初始状态应为
visibility: hidden; transform: translateX(-100%),而非display: none—— 后者会让 transition 直接失效
右侧抽屉的 transform 值怎么写才不翻车
写死 translateX(320px) 看似简单,但横竖屏切换、缩放、DPR 变化时会错位;用 100% 又依赖父容器宽度是否稳定。最稳做法是绑定自身宽。
- 给抽屉容器设固定宽:
width: 320px(别用vw,iOS Safari 渲染延迟明显) - 初始隐藏:
transform: translateX(100%)→ 此时 100% 按自身宽度算,刚好右边缘对齐视口右边界 - 展开状态:
transform: translateX(0),配合position: fixed; top: 0; right: 0; height: 100vh; - 加
will-change: transform(尤其旧安卓机或长列表场景下有实际提升)
点击穿透和键盘焦点怎么真正锁住
遮罩层 .overlay 设了 pointer-events: none 还是能点中底层按钮?那是因为 visibility 切换没同步,或 z-index 层级错乱。
- 遮罩层必须和抽屉同级,
z-index高于主内容、低于抽屉(如:主内容z-index: 1,遮罩z-index: 10,抽屉z-index: 11) - 打开抽屉时,同步设置:
.overlay { opacity: 1; visibility: visible; pointer-events: auto; } - 主内容区加
aria-hidden="true",抽屉加aria-modal="true" tabindex="-1",首次展开后立即focus()到抽屉内第一个可聚焦元素 - 关闭时,先
visibility: hidden,再等transitionend后清空aria-hidden和恢复 Tab 流
移动端 body 滚动禁用别碰 overflow: hidden
body { overflow: hidden } 在 Safari 下会强制跳回顶部,且关闭后 scrollX 残留导致页面横向偏移——这不是 bug,是 WebKit 的已知行为。
- 打开抽屉时执行:
document.body.style.overflowX = 'hidden'(仅锁 X 轴) - 关闭后设为
document.body.style.overflowX = ''(不是'auto') - 主内容区若本身可滚动,额外加
touch-action: pan-y,防 iOS 上滑误触内容区 - 抽屉父 wrapper 加
overscroll-behavior: contain,切断滚动链路,避免“抽屉没动,背后内容在滚”的断裂感
最容易被忽略的是:抽屉收起后,焦点没回到触发按钮,键盘用户得连按七八次 Tab 才能回来;还有遮罩层 opacity 动画没配 visibility 时长,导致鼠标悬停时穿透点击。这些不是“锦上添花”,而是 a11y 合规的硬门槛。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











