抽屉式侧边弹窗必须用 translate-x-full(右)或 -translate-x-full(左)配合 fixed 定位实现,禁用 hidden、left 或 width 过渡;容器自身须设 fixed 且显式声明初始位移类,遮罩需同级、z-index 略低并绑定关闭逻辑。

抽屉式侧边弹窗必须用 translate-x-full(右抽屉)或 -translate-x-full(左抽屉)配合 fixed 定位实现,不能靠 hidden、left 或 width 过渡——前者无动画,后两者掉帧、错位、不响应视口变化。
抽屉容器必须自身设 fixed,且初始位移类不可省略
常见错误是把 fixed 加在抽屉内部子元素上,而外层容器仍为 static。这会导致父容器继续占文档流空间,页面底部出现多余滚动条,iOS 下尤其明显。
- ✅ 正确写法:
<div class="fixed inset-y-0 right-0 z-50 w-64 -translate-x-full transition-transform duration-300 ease-in-out"> <li>❌ 错误写法:外层 <code>div无fixed,仅内部div加fixed和translate-x-full -
-translate-x-full必须显式写出,哪怕它看起来“和默认值一样”——浏览器需要明确起始transform才能插值动画 - 别用
translate-x-[-100%]:百分比依赖父宽,fixed元素父容器宽度常未定义,偏移不准;translate-x-full更可靠,移动端可进一步强化为translate-x-[100vw] - 遮罩应写在抽屉同级位置,用
fixed inset-0 bg-black/50 z-40 cursor-pointer - 点击遮罩关闭时,必须检查
event.target === overlayElement,防止抽屉内按钮点击冒泡触发二次关闭 - 加
tabIndex={0}并监听onKeyDown捕获Escape,否则键盘用户无法关闭 - 别给遮罩设
pointer-events-none——那会让点击完全失效;也别设pointer-events-auto(这是默认值),除非你真在覆盖其他层 - 根容器设
h-screen(占满视口高) - 内容区用
flex flex-col flex-1 overflow-y-auto,或更稳妥的max-h-[calc(100vh-80px)](预留头部高度) - 若顶部有固定导航栏(如
h-[63px]),则内容区高度必须严格对应:h-[calc(100vh-63px)] - 务必加
min-h-0(Safari 中防止 flex 子项拒绝收缩) - 结构上:移动端用
sm:hidden隐藏汉堡按钮,桌面端用md:block显示常驻侧边栏 - 动画上:桌面端直接移除
transition-transform和位移类,比如加md:translate-x-0 md:static md:inset-0 - 遮罩上:用
sm:hidden控制遮罩仅在移动端显示,且必须与抽屉同级、z-40 - 别写
sm:translate-x-0 md:-translate-x-full——语义反了,大屏反而隐藏
遮罩层必须与抽屉同级、z-index 略低、且绑定关闭逻辑
遮罩不是抽屉的子元素,否则滚动时会跟着动,失去“锁定背景”效果;也不能 z-index 太高,否则盖住抽屉本身。
内容区滚动必须独立控制,不能靠 h-full
抽屉高度常超视口,但直接套 h-full 在 fixed 元素里基本无效:它继承的是脱离流后的父高(常为 0),导致 overflow-y-auto 不触发滚动。
立即学习“前端免费学习笔记(深入)”;
响应式断点要分结构、动画、遮罩三层处理
桌面端不该有抽屉动画,也不该出现遮罩;但很多人只改 w- 类,结果小屏抽屉没关、大屏侧边栏又消失。
最容易被忽略的是焦点管理:抽屉打开时没自动聚焦首项,关闭时没把焦点还给汉堡按钮,WCAG 审计会直接失败;还有 will-change: transform 必须只在动画期间动态加 class 控制,长期开启有内存泄漏风险。



















