真正顺滑的滑动只依赖 transform: translatex() + transition;侧边栏用 position: fixed + overflow: hidden 防穿透;触控用 touchstart 替代 click 并防 300ms 延迟;js 控制类名 + transitionend 监听是唯一兼顾稳定性、可访问性与扩展性的方案。

transform: translateX() 是唯一靠谱的滑动实现方式
别碰 left、margin-left 或 display: none——这些要么强制重排导致卡顿,要么无法过渡直接闪现。真正顺滑的滑动只依赖 transform: translateX() + transition,它走 GPU 合成器,iOS Safari 和低端安卓 WebView 里都扛得住。
实操要点:
- 侧边栏初始状态设
transform: translateX(-100%)(完全左移出屏),宽度需明确(如width: 280px) - 主内容区加
transition: transform 0.3s ease,展开时向右平移相同距离腾出空间 - 用单一布尔类名(如
is-open)同时控制侧边栏和主区,避免 JS 多处操作样式失同步 - 必须加
will-change: transform,尤其在安卓 WebView 中,否则动画掉帧明显
fixed 定位 + overflow: hidden 是防穿透底线
侧边栏用 position: absolute 很容易被父容器的 overflow: hidden 截断;用 sticky 在滚动时行为不可控;只有 position: fixed 能确保它始终贴左、不随页面偏移、层级独立。
但光 fixed 不够——背后内容仍可滚动、点击、Tab 焦点穿透,这既违反可访问性,也容易误触。
必须同步做三件事:
- 菜单打开时,给
加overflow: hidden,禁用背景滚动 - 主内容区动态设
aria-hidden="true",侧边栏设aria-hidden="false" - 监听
keydown:按Escape关闭菜单;Tab 键只在菜单内循环(用document.querySelectorAll("a, button, [tabindex]")手动管理焦点)
touchstart 替代 click 防 300ms 延迟
在 iOS 和部分安卓浏览器中,click 有约 300ms 延迟,用户点一下没反应、再点才动,体验极差。这不是 bug,是浏览器为双击缩放留的判断窗口。
解决方案很简单:
- 触发按钮绑定
touchstart,并立即调用event.preventDefault() - PC 端 fallback 回
click:用'ontouchstart' in window ? 'touchstart' : 'click'判断 - 加
touch-action: manipulation和cursor: pointer,部分浏览器会自动消除延迟 - 千万别只靠
classList.toggle()——快速连点会导致动画未结束就再次触发,状态错乱。应维护一个isSidebarOpen变量,并监听transitionend事件确认动画完成
Checkbox Hack 适合纯静态页,但有硬伤
如果你真不想写 JS,<input type="checkbox" id="drawer-toggle"> + :checked ~ .drawer 是可行的纯 CSS 方案。但它本质是“伪交互”:状态无法持久、不能响应 history.pushState、关掉页面再打开就重置,且多级嵌套几乎不可控。
适用场景非常窄:
- 单页文档锚点导航(比如 API 文档侧边目录)
- 营销落地页,无登录态、无用户操作记忆需求
- 嵌入式设备 Webview,JS 运行环境受限
一旦涉及用户状态、权限控制或路由跳转,就必须上 JS 控制类名 + transitionend 监听——这是目前唯一能兼顾稳定性、可访问性和扩展性的路径。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











