原生HTML+CSS+JS实现侧边抽屉需三部分:遮罩层、抽屉容器、触发按钮;抽屉默认left:-100%,打开时left:0并设overlay opacity为0.5;须用transform/opacity过渡而非display,配合transitionend事件控制状态同步与滚动禁用。

HTML 本身不提供“抽屉”组件,drawer 是 UI 框架(如 Material Design、Ant Design)或 JavaScript 控制的交互行为,纯 HTML+CSS 只能实现静态结构和基础显隐逻辑;真要“可交互、有动画、适配移动端”的抽屉,必须配合 CSS transform + transition 和 JS 控制 classList 或 aria-expanded 状态。
怎么用原生 HTML+CSS+JS 实现一个可开关的侧边抽屉
核心是三块:遮罩层(overlay)、抽屉容器(drawer)、触发按钮(menu-button)。抽屉默认 position: fixed + left: -100%,打开时改为 left: 0,同时 overlay opacity 从 0 → 0.5。
- 抽屉宽度建议设为
width: 280px(兼顾触控与阅读,过宽在小屏上挤压内容) - 必须加
aria-hidden="true"初始状态,并在 JS 中同步切换,否则屏幕阅读器会误读隐藏内容 - 移动端需禁用 body 滚动:
document.body.style.overflow = 'hidden',关闭时恢复,否则抽屉内滚动会透出背景页 - 过渡动画只作用于
transform或left,避免直接动画display或visibility—— 它们不可过渡,会导致闪跳
为什么不能只用 display: none 切换抽屉
display: none 会让元素完全脱离文档流,无法触发 CSS 过渡(transition 对它无效),且重新显示时 DOM 重排开销大,尤其抽屉内有图片或复杂表单时,会明显卡顿。
- 正确做法是用
opacity+transform: translateX()控制显隐,保持元素在渲染树中 - 若需彻底卸载(比如抽屉内容极重),应在动画结束后用 JS 移除或清空子节点,而非靠
display隐藏 - 某些旧版 iOS Safari 对
transform: translateX(-100%)渲染异常,可改用left: -100vw作为兜底
抽屉里放表单或输入框时,键盘弹出会把抽屉顶上去怎么办
这是 iOS Safari 的经典 bug:软键盘弹出时,fixed 元素会随 viewport 缩小而上移,导致抽屉错位甚至消失。Android Chrome 一般无此问题。
立即学习“前端免费学习笔记(深入)”;
- 临时解法:监听
focus事件,在 input 获焦时给抽屉加position: absolute,并用 JS 动态计算top值(基于window.scrollY) - 更稳方案:放弃
position: fixed,改用position: absolute+inset-block-start: 0,并确保父容器position: relative - 务必测试真实设备 —— iOS 模拟器常不复现该问题
抽屉的“关”比“开”更难处理:要等动画结束再移除遮罩、恢复滚动、重置焦点,漏掉任一环都可能让页面卡死或键盘不收。别依赖 setTimeout,用 transitionend 事件才是可靠方式。



















