结论:用、、、、五个语义标签即可覆盖95%页面地标需求;显式写role属性通常冗余甚至有害,除非兼容ie或处理无对应语义标签的特殊模块。

直接说结论:用 <header></header>、<nav></nav>、<main></main>、<aside></aside>、<footer></footer> 这五个语义标签,就能覆盖 95% 的页面地标需求;显式写 role 属性通常是冗余甚至有害的,除非你正在兼容 IE 或处理无对应语义标签的特殊模块。
为什么不能靠 div + role 搭建地标结构
很多开发者习惯先用 <div class="header"> 再加 <code>role="banner",这看似“明确”,实则埋下三类问题:
- 屏幕阅读器可能忽略重复或冲突的语义(比如同时存在
<header></header>和<div role="banner">) <li>浏览器可访问性树会生成冗余节点,导致用户在地标导航时被卡在“两个 banner”之间来回跳转</li> <li>WAI-ARIA 第一条规则明确要求:「有原生语义标签时,优先使用它」——<code><header></header>就是role="banner"的原生实现,无需额外标注 - 一个页面只能有一个
<main></main>;第二个会被浏览器静默忽略,Lighthouse 直接报document-has-main-element错误 -
<main></main>不能作为<header></header>、<nav></nav>、<footer></footer>或<aside></aside>的子元素——否则搜索引擎和屏幕阅读器会认为“核心内容在页脚里”,逻辑崩坏 - 允许
<main></main>内部包含自己的<header></header>(如文章标题区)或<footer></footer>(如发布时间),但它们属于内容级,不参与页面级地标导航 -
<section></section>必须有主题,且应紧邻一个<h2></h2>~<h6></h6>标题;纯靠 CSS margin 分隔的区块不该用<section></section> -
<article></article>要求内容能脱离当前页面独立存在(如 RSS 订阅、转发到社交平台),博客正文、新闻稿适用;用户评论、广告位、侧边推荐栏不适用 - 把多个
<article></article>套在同一个<main></main>下是合理结构;但用多个<main></main>包裹每个<article></article>是严重错误 -
<nav></nav>专指**主要导航链接集合**(如顶部菜单、面包屑、页脚导航),必须含多个<a></a>或<button></button>;单个“返回首页”链接不构成<nav></nav> -
<aside></aside>表示**与主内容相关但可独立存在**的信息(作者简介、延伸阅读、相关产品推荐),不是“侧边栏视觉位置”的代名词;如果右侧区块是广告或登录框,它更该用<section></section>+aria-label明确说明用途 - 不要给
<aside></aside>加role="complementary"——它本就隐式对应此角色;手动添加反而可能触发旧版读屏软件的兼容问题
main 标签的唯一性与嵌套限制必须硬性遵守
<main></main> 不是“样式容器”,而是辅助技术识别“核心内容”的唯一锚点。违反规则会导致内容被跳过或降权:
section 和 article 的语义边界决定地标有效性
这两个标签不是“视觉分块工具”,而是向辅助技术声明“这里有一段可独立理解的内容”。滥用会导致地标结构失真:
aside 和 nav 的角色不能互换
<aside></aside> 和 <nav></nav> 都是地标,但意图完全不同,混用会误导辅助技术用户:
真正难的不是写对标签,而是判断每个区块在用户心智模型中的定位:它是导航入口?核心信息?上下文补充?还是装饰性噪音?语义标签的本质,是把这种判断固化为机器可解析的信号。一旦开始按这个思路组织 DOM,地标结构自然清晰,无障碍和 SEO 都只是顺带结果。











