一个页面应有且仅有一个语义正确的,代表当前页核心主题:首页用站点定位,文章页用文章标题,产品页用具体产品名;不可用于样式控制,须通过css调整外观;html5允许多个仅限于独立语义区块(如)内;动态框架中需避免ssr/csr导致的缺失或重复。

一个页面只能有一个 <h1></h1>,且必须代表页面核心主题
搜索引擎和屏幕阅读器都依赖 <h1></h1> 判断“这页到底讲什么”。如果首页放了 <h1></h1>“公司简介”,文章页却用 <h1></h1>“联系我们”,机器会困惑主内容到底是哪个。真实场景中,CMS 模板常在 header 区硬编码一个 <h1></h1> 网站名,再在正文又塞一个文章标题,结果页面出现两个 <h1></h1> ——这是最常见也最伤 SEO 的错误。
- 首页:用
<h1></h1>表达站点定位,比如<h1>上海前端开发工作室</h1> - 文章页:
<h1></h1>必须是当前文章标题,比如<h1>React 19 中 useActionState 的实际陷阱</h1> - 产品页:不是“产品列表”,而是具体产品名,比如
<h1>MacBook Pro 16 英寸(M4 Pro)</h1>
<h1></h1> 不是样式工具,别用它控制字号或居中
有人看到默认 <h1></h1> 太大,就加 style="font-size:18px;" 压缩;或者为了居中写 align="center"。这等于把语义标签当 div 用。一旦改版或接入无障碍工具,视觉正常但逻辑断裂——屏幕阅读器仍会高亮播报“一级标题”,而用户听到的却是被压缩成小字的普通文本。
- 所有视觉调整交给 CSS:
h1 { font-size: 2rem; text-align: center; margin: 0.5em 0; } - 禁止在
<h1></h1>标签里写class以外的呈现属性(如align、color、size) - 如果 CMS 输出不可控,宁可用 JS 动态移除多余
<h1></h1>,也不要妥协语义
HTML5 允许多个 <h1></h1>?前提是语义区块隔离
HTML5 规范确实允许在 <article></article> 或 <section></section> 内部各自用 <h1></h1>,但这不等于可以随意堆砌。真实项目里,95% 的误用都源于没搞清“独立语义上下文”这个前提。
- 正确场景:博客首页列出 5 篇文章,每篇用
<article><h1>标题</h1>...</article>—— 每个<article></article>是自包含内容单元 - 错误场景:在同一个
<main></main>里并列写两个<h1></h1>,中间没有任何语义容器包裹 - 检查方法:用浏览器开发者工具右键审查元素,看
<h1></h1>是否严格落在<article></article>/<section></section>内部,且父容器有明确 role 或 aria-label
动态页面中 <h1></h1> 容易被 SSR/CSR 搞丢或重复
Next.js、Nuxt 或 Vue SPA 在首屏渲染时,常因数据加载时机问题导致 <h1></h1> 缺失;服务端渲染时又可能把 layout 固定的 <h1></h1> 和页面组件里的 <h1></h1> 一起吐出来。这类问题不会报错,但 Google Search Console 会标记 “Missing H1” 或 “Multiple H1s”。
- Next.js App Router:确保只在
page.tsx中定义<h1></h1>,layout.tsx 里彻底删掉任何<h1></h1> - Vue/Nuxt:用
<clientonly></clientonly>包裹动态标题,避免服务端预渲染出空<h1></h1> - 上线前必做:用 Lighthouse 扫描,重点关注 “Document does not have a main landmark” 和 “Heading elements are not in a sequentially-descending order” 这两条
<h1></h1>,而是让整个团队在模板、CMS、前端框架、SEO 配置之间达成一致——只要有一环松动,<h1></h1> 就会悄悄失效。











