最稳抽屉式折叠用 transform: translateX() 实现,需配合 fixed/absolute 定位、flex 布局解耦、checkbox hack 状态记忆及无障碍属性同步,避免 width 动画卡顿与移动端手势冲突。

用 transform: translateX() 实现抽屉式折叠最稳
直接改 width 或 left 容易卡顿、跳变、触发重排;transform: translateX() 走 GPU 加速,动画顺,且不干扰文档流。关键不是“怎么写”,而是结构和配套必须到位。
- 侧边栏必须设
position: fixed或position: absolute,否则transform会把页面内容挤动 - 隐藏态用
transform: translateX(-100%),别用left: -300px—— 后者依赖具体像素值,响应式下易失效 -
.overlay遮罩层要和侧边栏同级,z-index高于主内容但低于侧边栏,否则点不到按钮或遮不住 - 移动端必须加
touch-action: pan-y到侧边栏上,否则手势滑动会和页面滚动冲突
用 flex 布局解耦侧边栏与主内容宽度
靠 margin-left 手动同步侧边栏宽度,一换屏就错位;用 flex 让主内容自动填满剩余空间,才是健壮解法。
- 父容器设
display: flex+min-height: 100vh,避免 sticky 失效或高度塌陷 - 侧边栏写
flex: 0 0 240px(不伸展、不收缩、固定宽),折叠时切 class 改为flex: 0 0 60px - 主内容区用
flex: 1,别写死width或margin,否则响应式断点里要重复写多套规则 - 如果侧边栏是
position: fixed,主内容就得用padding-left替代margin-left,否则它不占文档流
用 checkbox hack 实现纯 CSS 状态记忆
刷新后仍保持折叠/展开状态,不用 JS 存 localStorage —— input[type="checkbox"] 是唯一原生支持状态持久化的 HTML 元素。
-
input必须放在 DOM 最前,紧挨着label,后面所有被控元素用兄弟选择器:checked ~ .sidebar-item控制 - 折叠时用
display: none,不是visibility: hidden或opacity: 0—— 后两者仍占 tab 顺序和布局空间 - 同步设
tabindex="-1"和aria-hidden="true",否则键盘用户会聚焦到不可见菜单项上 - 移动端小屏下,强制给子菜单加
display: none !important,一级热区尺寸不低于44×44px
为什么 width 过渡常失败?三个硬性条件缺一不可
不是写错了 transition,而是没满足浏览器做 width 动画的前提:初始值明确、flex 不覆盖、溢出可控。
立即学习“前端免费学习笔记(深入)”;
- 侧边栏必须显式声明初始
width: 240px,不能是auto或fit-content,否则过渡无效 - 若父容器是
display: flex,width会被flex-basis覆盖,此时得改flex-basis并配min-width: 0 - 必须同时加
overflow: hidden和transition: width 0.3s, overflow 0.3s,否则收起瞬间内容会闪出边界 - 永远别写
width: 0—— 含 flex 子项或 inline-block 的菜单会布局崩溃;用width: 60px(图标区宽度)更安全
aria-expanded、aria-hidden)不同步,以及移动端 touch 事件和页面滚动的冲突处理——这两处一出问题,用户根本点不动、看不见、也划不走。



















