导航条必须用包裹且内部用结构,因提供语义标识,配合嵌套确保屏幕阅读器识别导航意图、搜索引擎理解链接用途,并支持可访问性交互;错误结构会导致读屏误读、lighthouse报错及焦点混乱。

导航条区域必须用 <nav></nav> 包裹,内部必须用 <ul></ul> 和 <li> 构建结构 —— 这不是“推荐做法”,而是语义正确性和可访问性的硬性要求。
为什么不能直接用 div + a 做导航
屏幕阅读器会把 <div>@#@#@#@#@#@#@#@#@#@0<h3>CSS 排版时 display: inline-block 和 flex 的取舍</h3>
<p>老式写法用 <code>li { display: inline-block; } 或 li { float: left; } 实现横排,但存在基线对齐、空白符换行、清除浮动等隐性问题。现代项目应优先用 display: flex:
<nav aria-label="主导航"><ul>
<li><a href="/">首页</a></li>
<li>
<a href="/products">产品</a>
<ul>
<li><a href="/products/web">Web 工具</a></li>
<li><a href="/products/cli">命令行</a></li>
</ul>
</li>
</ul></nav>
注意:
– 不要给 <li> 设固定宽度,它应由内容撑开
– gap 在 Flex 中比 margin-right 更安全,避免最后一项多出空白
– 若需兼容 IE11,仍得回退到 inline-block,但必须设 font-size: 0 在父 <ul></ul> 上消除空白符间隙
容易被忽略的可访问性细节
很多开发者写了语义结构,却漏掉几个关键属性,导致导航在键盘或读屏下不可用:
– <nav></nav> 必须带 aria-label,如 <nav aria-label="主导航"></nav>;若页面有多个 <nav></nav>(比如页脚也有),必须区分 label
– 子菜单触发按钮(如“产品”文字链接)需加 aria-haspopup="menu" 和 aria-expanded="false",并在 JS 切换时同步更新 aria-expanded
– 键盘操作必须支持 Tab 进入、→← 切换、Enter 展开、Esc 关闭、↓ 进入子菜单 —— 这些不是 CSS 能解决的,必须配合 JS 实现焦点管理
– <ul></ul> 上不要加 role="navigation",因为 <nav></nav> 已自带该 role,重复会导致读屏重复播报
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
gap: 1rem; /* 比 margin 更可控,不需处理最后一个元素 */
}
<p>nav ul li a {
display: block;
padding: 0.5rem 1rem;
text-decoration: none;
}</p>











