必须用<nav>包裹主导航链接并配<ul>结构和aria-label,禁用<div class="nav">;当前页需设aria-current="page",下拉菜单须支持键盘操作与ARIA属性。

用 <nav> 包裹导航结构,别直接用 <div>
语义化是第一步,<nav> 告诉浏览器和读屏软件“这是主要导航区域”,对 SEO 和可访问性都有实际影响。很多新手直接套 <div class="menu">,结果在屏幕阅读器里被读成“普通容器”,用户得手动摸索。
常见错误现象:Navigation landmark not found(Lighthouse 或 axe 插件报的可访问性警告)
- 必须把主导航项(如首页、关于、联系)放在
<nav>内,页脚链接或面包屑一般不用 - 一个页面通常只用一个
<nav>;多个时建议加aria-label区分,比如<nav aria-label="主导航"> - 不要嵌套
<nav>—— 比如下拉菜单里再写一层<nav>,反而干扰语义
链接用 <a>,当前页用 aria-current="page"
别用 <button> 或 <span> 模拟链接,那不是导航,是自造障碍。真实跳转必须靠 <a href="..."></a>。
当前激活页的处理很关键:纯靠 CSS 类(如 class="active")无法被读屏器识别,必须加 aria-current="page"。
立即学习“前端免费学习笔记(深入)”;
-
<a href="/about" aria-current="page">关于</a>—— 读屏器会读作“关于,当前页面” - 不要写
aria-current="true"或aria-current="active",只有"page"、"step"、"location"是合法值 - 服务端渲染时由后端判断并注入该属性;前端路由(如 React Router)需用
useLocation+aria-current手动同步
水平排列用 display: flex,别依赖 float 或 inline-block
float 已淘汰,inline-block 有看不见的空白符问题(换行/缩进会变间距),Flex 是目前最稳的方案。
nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
nav li { margin-right: 1rem; }
nav a { text-decoration: none; color: #333; }
- 必须重置
ul的默认margin和padding,否则左右留白不一致 - 移动端要加
@media折叠为汉堡菜单,但基础 HTML 结构不变 —— 别为了“响应式”把<ul><li>换成<div>堆砌 - 如果用 CSS Grid 替代 Flex,注意
grid-auto-flow: column才能横排,且兼容性略低(IE 不支持)
下拉菜单必须支持键盘操作,hover 不够用
仅靠 :hover 实现下拉,在触屏设备和键盘用户(Tab 键导航)面前完全失效。真实可用的下拉需要 focus、keydown 和 ARIA 属性配合。
- 父级
<li>加role="menuitem",子菜单<ul>加role="menu"和hidden属性 - 用
Enter/Space展开,Esc收起,ArrowDown进入子项 —— 这些不能只靠 CSS - JavaScript 必须监听
focusin事件来动态控制hidden,而不是只靠:focus-within(Safari 旧版不支持)



















