一个页面必须且只能有一个<h1>,它是文档唯一主语义锚点;<h2>至<h6>须严格逐级嵌套、不可跳级,<section>或<article>内可独立设<h1>,但需满足语义隔离条件。
<h1>
只有一个 <h1> 是硬性语义要求,不是“建议”。它代表整个文档的唯一主旨,搜索引擎和屏幕阅读器都依赖这个信号定位核心内容。多出一个,比如 CMS 模板里塞了个 <h1> Logo,正文又加一个 <h1> 标题,结果就是大纲分裂——两个节点都被识别为根,辅助技术会困惑“哪个才算主?”
例外只发生在语义隔离场景:<article> 或 <section> 内部允许有自己的 <h1>,但前提是这个区块能独立分发(比如博客列表页里的单篇摘要)。普通卡片、侧边栏、表单区块不在此列,用 <h2> 更安全。
常见踩坑点:
<h1> 被包裹在 <div class="wrapper"> 里,看似在 <main> 下,实则中间插了一层无语义容器,破坏了直接父子关系<h1>
<h1> 却没删标签,结构仍在,但对用户不可见<h2> 到 <h6> 的嵌套必须连续,不能跳级跳级不是样式问题,是语义断裂。写 <h2> 后直接跟 <h4>,浏览器不会报错,但大纲生成算法会强行把 <h4> 当作 <h3> 的子项推断层级,而实际内容逻辑可能完全不匹配——屏幕阅读器用户导航时会卡在错位的结构里。
立即学习“前端免费学习笔记(深入)”;
真正决定层级归属的,不只是标签名,还有它所处的语义容器:
<main> 直接子级的 <h2>,就是一级章节<section> 内的 <h3>,哪怕数字比外面的 <h2> 小,也会被识别为该 <section> 的顶层标题<h3> 被塞进 <p> 或 <div>,它就脱离了合法上下文,部分读屏器直接忽略<section> 和 <article> 会影响标题解析<section> 不是“装内容的盒子”,它是 sectioning root,会重置内部 heading 的隐含层级计数。没有它,所有 <h2>~<h6> 都在同一个全局大纲树里平铺;有了它,每个区块获得独立上下文。
举个实际例子:
<main> <h2>产品参数</h2> <section> <h3>尺寸</h3> <p>长宽高...</p> </section> <section> <h3>材质</h3> <p>铝合金...</p> </section></main>
这里两个 <h3> 是并列的子节,属于同一个 <h2> 下的分支。但如果去掉 <section>,直接写 <h3>,它们就会被当成跳级节点,Accessibility 面板标红警告。
注意:空的 <section> 仍会进入大纲,显示为“无标题”,对可访问性不利——每个 <section> 必须以对应层级的 heading 开头。
别等上线再查。打开 Chrome DevTools → Elements 面板 → 右键任意 <h1>~<h6> 元素 → “Inspect ARIA attributes”,看 aria-level 是否连续、是否符合你预设的内容逻辑。
重点盯三处:
<h1> 是否唯一,且是 <main> 的直接子元素(中间不能有 <div>)<h2> 后直接 <h4> 这类跳级<section>、<article> 是否以 <h2> 或更高层级 heading 开头最常被忽略的,不是“用了什么标签”,而是“它在哪儿、被谁包裹、和谁并列”。结构问题往往藏在嵌套深处,而不是标签本身。