侧边栏该用nav而非aside,因其本质是导航行为;若含跳转链接如“API文档”“章节锚点”,必须用确保读屏器识别,aside仅适用于作者简介等补充内容。

侧边栏该用 nav 还是 aside?先看它是不是导航行为
如果侧边栏里全是跳转链接(比如“API 文档”“用户设置”“章节锚点”),它就是导航,必须用 nav,并加 aria-label。屏幕阅读器只把 nav 当作可跳转的导航区域,aside 没这个能力。
常见错误:用 div 包菜单、或用 aside 替代 nav,结果读屏器直接跳过整个区块,键盘 Tab 也卡不住焦点。
-
nav适合主导航、文档大纲、章节跳转等有明确跳转意图的结构 -
aside只适合补充内容,如“相关文章”“作者简介”“术语解释”,且必须嵌套在语义合理的位置(与main并列,或在article内部) - 多个导航区共存时(比如页头主导航 + 侧边栏导航),要分别加
aria-label,例如aria-label="主站点导航"和aria-label="文档目录导航"
role="navigation" 是冗余的,但 aria-current 必须手动同步
nav 元素天然带 role="navigation",再显式写一遍纯属重复,还可能干扰某些旧版辅助技术。真正关键的是当前激活项的状态表达——aria-current="page" 或 aria-current="section"。
它不会自动更新。JS 切换选中项时,必须手动设置:
el.setAttribute('aria-current', 'page');
同时清除上一个元素的该属性。否则读屏器无法感知“你现在在哪一页”。
- 静态页面可用
:target配合 JS 初始化,但别指望它持久化状态 - 子菜单展开时,父级
li要加aria-expanded="true",并确保对应子ul的aria-hidden值同步翻转 - 禁用项不能只靠 CSS 灰掉,得加
aria-disabled="true"并移除href或设tabindex="-1"
视觉隐藏 ≠ 语义隐藏:别用 display: none 收起侧边栏
移动端收起侧边栏时,如果只用 display: none,键盘用户 Tab 会直接跳过整个区域,读屏器也不会播报——这不是“隐藏”,是“丢弃”。
正确做法是保留 DOM,用视觉隐藏 + 语义控制双保险:
- CSS 用
position: absolute; clip-path: inset(100%);或clip: rect(1px, 1px, 1px, 1px);隐藏但不移出流 - HTML 层面同步加
aria-hidden="true"和inert属性(inert更彻底,现代浏览器已支持) - JS 切换时,记得给
body加overflow: hidden,防止背景内容还能滚动 - 动画优先用
transform: translateX(),避免left触发重排,低端安卓机上尤其明显
Flex 布局下,nav 宽度飘忽的根源是没切断父级影响
很多侧边栏一动就塌,不是 CSS 写错了,而是 nav 在 display: flex 的父容器里被压缩了,或者内部 ul 的 margin 外溢导致整体偏移。
必须做两件事:锁定尺寸边界 + 阻断外溢影响。
- 最外层
nav加flex-shrink: 0,防止被 flex 主轴压缩 - 用
min-width: 240px控制基础尺寸,比width更兼容折叠逻辑 - 内部
ul显式重置margin: 0,避免默认样式外溢 - 固定定位(
position: fixed)时,务必同时设top: 0和left: 0,Safari 不认单边声明
最难的不是让侧边栏看起来像导航,而是每次点击、收起、滚动后,DOM 结构、焦点顺序、ARIA 状态、CSS 渲染层这四者是否始终对齐——漏掉任意一个,用户就会卡在某个看不见的按钮上。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











