只能有一个且必须为直接子元素,因其是页面唯一语义主干,重复或嵌套会破坏可访问性、导致屏幕阅读器跳过核心内容、seo降权及lighthouse报错。

语义化结构不是加几个新标签就完事,而是从内容意图出发选对标签——错用 <section></section> 比不用更糟,多写一个 <main></main> 会直接破坏可访问性。
怎么判断该用 <header></header> 还是 <section></section>
看这块内容是否承担“页面或区块的头部功能”:<header></header> 必须出现在逻辑容器顶部(如整个页面、一篇 <article></article> 或一个 <section></section> 内),里面放 logo、标题、搜索框、登录入口都合理;<section></section> 则必须自带独立标题(<h2></h2>–<h6></h6>),且内容能被单独理解或复用(比如“技术方案”“用户反馈”这类有明确主题的区块)。
常见错误:
- 把整页顶部导航栏包进
<section></section>—— 它没标题,也不独立,该用<header></header> - 在
<header></header>里塞进“关于我们”链接列表 —— 这属于页脚信息,不是页头职责 - 用
<section></section>包裹单个段落而无标题 —— 语义断裂,浏览器和屏幕阅读器无法识别其作用
<main></main> 只能有一个,但很多人误把它当“主要内容区”来用
<main></main> 的语义是“页面唯一核心内容”,不是“视觉上居中的区域”。它不能嵌套在 <article></article>、<section></section> 或 <aside></aside> 里,也不能出现两次。
典型误用场景:
- 在博客首页,把每篇
<article></article>都包进一个<main></main>—— 错,整个文章列表才是<main></main>,每篇<article></article>是它的子项 - 把侧边栏的“热门标签”放进
<main></main>—— 它属于辅助内容,该放<aside></aside> - 在登录页把表单和说明文字一起塞进
<main></main>—— 如果页面只有这个表单,可以;但如果页头有 logo、页脚有版权,那<main></main>就只能包表单本身
<nav></nav> 不是“有链接就是导航”,得看跳转目的
<nav></nav> 的语义是“提供主要导航路径”,即帮助用户在站点内不同区域/页面间移动。面包屑、主导航、页脚的“产品/文档/支持”链接组都算;但文章末尾的“相关推荐”、评论区的“回复按钮”不算。
实操建议:
- 多个
<nav></nav>共存没问题,但必须加aria-label区分,例如<nav aria-label="主导航"></nav>和<nav aria-label="页脚导航"></nav> - 纯 JS 跳转的 tab 切换菜单,如果没真实 URL,别硬套
<nav></nav>—— 它不满足“导航”语义,用<div role="tablist"> 更准确 <li>搜索框本身不是导航,但搜索结果页的分页条(“第1页 / 第2页”)是,该用 <code><nav></nav> -
role:应为banner(<header></header>)、navigation(<nav></nav>)、main(<main></main>) -
name:若为空,可能缺aria-label或内部标题(如<nav></nav>没aria-label,屏幕阅读器读不出这是啥导航) -
level:标题层级必须连续,<h2></h2>后接<h4></h4>会导致跳级,辅助工具无法正确建立大纲
检查语义是否真正生效,光看标签名不够
写了 <header></header> 不代表浏览器就认它是页头。打开 Chrome DevTools → Elements 面板 → 右键元素 → “Inspect Accessibility Properties”,重点看三列:
最容易被忽略的是:用 CSS 隐藏了某块 <nav></nav>(display: none),却没同步加 aria-hidden="true" —— 屏幕阅读器仍会尝试读取它,造成干扰。











