<header>仅在<body>或顶级sectioning元素中才隐式为role="banner";<main>必须唯一且仅含页面独有内容;<nav>需为全局主导航;搜索须用<form role="search">。

banner角色对应,但不是所有header都该用
浏览器和读屏软件把 <header> 当作隐式 role="banner",前提是它直接属于 <body> 或顶级 sectioning 内容(比如没被 <article> 包裹)。如果只是某个 <section> 里的头部,比如“章节标题+简介”,那它语义是局部的,不该触发 banner landmark。
常见错误现象:<body><header><h1>首页</h1></header><main>...</main> 这样写没问题;但写成 <article><header><h2>一篇博文</h2></header>...</article> 时,这个 <header> 就不该被当成 banner —— 它没有全局性,读屏器也不会把它列进 landmark 列表。
- 只在页面最外层、代表整个站点身份的区域用
<header>(含 logo、主标题、全站搜索) - 嵌套在
<article>、<section>里的<header>自动降级为普通结构容器,无需也不应加role="banner" - 旧项目里用
<div role="banner">的,现在优先换成<header>,语义更干净,兼容性也更好
main元素必须唯一,且不能包含重复内容
<main> 是页面里唯一能带隐式 role="main" 的标签,它的核心约束就两条:只出现一次、只包裹当前页独有的主体内容。一旦违反,读屏器会跳错位置,axe 等审计工具也会报 landmark-no-duplicate-main。
典型踩坑场景:<main><header>...</header><nav>...</nav><article>正文</article></main> —— 这里把 <header> 和 <nav> 塞进 <main>,等于让它们既算 landmark 又算主要内容,逻辑冲突。
立即学习“前端免费学习笔记(深入)”;
-
<main>应紧接在<nav>或<header>之后,且内部只放文章、产品列表、表单等不可复用的核心块 - 页脚链接、侧边栏、面包屑、版权声明这些重复性内容,一律排除在
<main>外 - SSR 框架(如 Next.js)生成 HTML 时若漏掉
<main>,会导致无障碍测试失败,不是可选项
navigation角色靠
<nav> 的隐式 role="navigation" 只对「全局性、重复性、主导航用途」的链接集合生效。它不是“有链接就套”,而是要匹配用户心智模型里的「导航」——比如顶部菜单、左侧分类栏、页脚快速入口。
错误示例:<nav><a href="/prev">上一篇</a><a href="/next">下一篇</a></nav> —— 这类上下文相关链接属于内容流一部分,读屏器会按顺序读,强行加 <nav> 反而干扰跳转逻辑。
- 一个页面可以有多个
<nav>,但每个必须有独立导航目的(如顶部主菜单 + 页脚分类导航) -
<nav>内部不强制用<ul>,但避免塞按钮、表单控件等非跳转目标 - 需要区分多个导航区时(如“主菜单”和“语言切换”),务必加
aria-label,例如<nav aria-label="语言选择">
search landmark没有原生标签,得手动声明
HTML5 没给 search 地标配专用标签,<form> 是唯一推荐载体。直接写 <form role="search"> 即可触发隐式 landmark,读屏器会识别为“搜索区域”,支持快捷键跳转(如 NVDA+Insert+S)。
别用 <div role="search"> —— form 元素自带语义和键盘交互能力(回车提交),div 没有。也别把整个搜索框组件(含按钮、筛选项)全包进去,只包裹真正执行搜索动作的输入域和提交控件。
- 搜索框若放在
<header>里,仍需单独用<form role="search">包裹,不能依赖 header 的 banner 角色 - 页面中只能有一个
role="search",多个搜索框(如高级搜索弹窗)应通过aria-hidden或动态挂载控制可见性 - 旧 IE 或极老读屏器可能忽略
role="search",此时可加aria-label="站内搜索"保底



















