结论:用、、、四个语义标签即可覆盖90%长网页结构可访问性需求;手动添加role属性多属冗余甚至有害,仅在无法使用语义标签时才需补全。

直接说结论:用 <header></header>、<nav></nav>、<main></main>、<footer></footer> 这四个语义标签,就能覆盖 90% 的长网页结构可访问性需求;显式写 role 属性多数时候是画蛇添足,反而容易出错。
为什么不用手动加 role="banner" 这类属性?
因为现代浏览器和屏幕阅读器(NVDA、VoiceOver、JAWS)已原生支持 HTML5 标签的隐式地标角色。比如:<header></header> 自动对应 role="banner",<nav></nav> 对应 role="navigation",无需重复声明。
- 手动加
role="banner"到<header></header>不会报错,但属于冗余——可访问性树里会出现两个相同角色,部分旧版辅助技术可能混淆 - 若把
<header></header>嵌套在<article></article>或<section></section>内部,它就不再被识别为页面级banner,而是节级region;此时加role="banner"会强行“越权”提升层级,破坏结构逻辑 - 只有当必须用
<div> 模拟头部且无法改用 <code><header></header>(如遗留系统或框架限制),才考虑补role="banner"长网页中
必须唯一且不能嵌套 这是最容易翻车的地方:很多开发者把每个“模块”都包一层
<main></main>,以为能增强语义,结果让屏幕阅读器用户彻底迷失。-
<main></main>在整个文档中只能出现一次,代表页面核心内容的起始与边界 - 它不能是
<header></header>、<nav></nav>、<aside></aside>或另一个<main></main>的子元素;否则会被忽略或报错(Chrome DevTools 的 Accessibility 面板会标红) - 长网页常见错误:在 Tab 切换区域、折叠面板、分页卡片里各自放一个
<main></main>—— 正确做法是用<section></section>或<article></article>区分内容块,<main></main>只包裹它们整体
多个
长网页常有主导航、侧边导航、面包屑、页脚链接组,全用
<nav></nav>没问题,但必须靠aria-label或aria-labelledby区分用途。- 只写
<nav></nav>不加标识,所有导航区在屏幕阅读器里都读作“navigation”,用户无法分辨哪个是主菜单、哪个是相关链接 - 主导航建议:
<nav aria-label="主导航"></nav>;面包屑用<nav aria-label="当前位置"></nav>;页脚链接组用<nav aria-label="快捷链接"></nav> - 避免用
aria-label="导航"这种泛称——它和不写没区别;也不要用 class 名(如aria-label="footer-nav")替代自然语言
region 和 complementary 角色什么时候真需要?
这两个角色不是“锦上添花”,而是填补语义空白的最后手段,用错比不用更糟。
-
role="region"应仅用于没有合适语义标签、且确实具备独立功能的区域,例如:带实时更新的股票行情栏、多步骤表单的状态提示条;必须配aria-label(不能空) -
role="complementary"对应<aside></aside>,但仅当该侧边内容与当前<main></main>强相关(如博客文章旁的作者简介、术语解释框);纯广告或无关推荐用<aside></aside>即可,不必加 role - 滥用
role="region"是常见陷阱:把每个<div class="card"> 都塞一个 <code>role="region"+aria-label,会让屏幕阅读器用户听到一连串“region, region, region…”而失去上下文真正卡住人的从来不是怎么加地标,而是删掉多余地标——删掉那些为“看起来规范”而硬加的
role,删掉嵌套的<main></main>,删掉无意义的aria-label,结构自然就清晰了。
-











