按钮必须用 button 而不是 a 或 div,因其具备语义性、键盘可访问性且能通过 type="button" 避免默认提交;侧边栏收缩应采用 class 切换配合 css 宽度与可见性控制,禁用单纯 display 切换;需兼顾焦点管理、aria 属性、ios fixed 渲染缺陷及无障碍支持。

按钮必须用 button 而不是 a 或 div
用 a 标签容易触发页面跳转或默认行为,div 缺少语义和键盘可访问性。正确做法是:button 加 type="button" 显式禁用表单提交行为。
常见错误:漏写 type="button",在某些表单上下文中点击后整个页面刷新;或者用 onclick="toggle()" 却没阻止默认行为,导致意外跳转。
- 始终写成
<button type="button" id="sidebar-toggle"></button> - 图标建议用 SVG 或
<span aria-hidden="true">≡</span>,避免纯图片影响可访问性 - 为屏幕阅读器加
aria-expanded和aria-controls属性,例如:aria-expanded="false" aria-controls="sidebar"
toggle() 函数里别只改 display
单纯切换 display: none/block 会破坏过渡动画、丢失焦点管理、且无法实现“收缩到仅图标”的中间状态(比如宽度从 240px → 60px)。现代侧边栏收缩本质是状态驱动的宽度 + 可见性组合控制。
- 推荐用 class 切换:
sidebar.classList.toggle('is-collapsed'),CSS 中定义.is-collapsed { width: 60px; }和子元素的opacity/visibility控制 - 避免用
offsetWidth或getBoundingClientRect()做动画起点判断——DOM 读取会强制重排,卡顿明显 - 如果要用 JS 动画(如
animate()API),确保目标属性是width或transform,而非left+position: absolute(iOS fixed 容器滚动时易闪)
移动端真机测试时 position: fixed 很可能失效
iOS Safari 对 position: fixed 在滚动中渲染不稳定,尤其当侧边栏高度超过视口、或页面有 transform 父容器时,会出现抽搐、错位、甚至完全消失。
- 替代方案:用
position: absolute+ 手动监听scroll事件更新top值(注意节流) - 更稳妥的做法是放弃“永远固定”,改用“滚动时收起、悬停/点击再展开”逻辑,用
IntersectionObserver检测是否在视口内 - 务必在真机上验证:Safari 的
overflow-anchor: none可能干扰 fixed 元素定位,需额外重置
折叠后子菜单和键盘导航经常被忽略
视觉上收起来了,但 DOM 还在,Tab 键仍会依次聚焦所有隐藏项,用户卡在看不见的地方;屏幕阅读器也可能播报“首页(不可见)”这种无效信息。
- 用
aria-hidden="true"配合visibility: hidden或inert属性(支持度有限,需降级)屏蔽不可见项 - 折叠时把焦点移回触发按钮,展开后自动聚焦第一个可操作子项(
firstElementChild?.focus()) - 子菜单的展开/收起不能只靠
max-height过渡——它无法精确控制高度变化,推荐用height: 0→height: fit-content+overflow: hidden,或直接用clip-path
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











