<main>必须唯一且为body直接子元素,否则屏幕阅读器跳过主内容、Lighthouse报错、SEO降权;常见错误包括SPA路由未销毁旧main、CMS模板条件渲染漏判、将main嵌套在header或section内。

HTML语义化标签不是“写得规范一点”的装饰,而是决定你半年后还能不能快速定位、安全修改代码的硬性结构约束。
为什么改个导航要动五个文件?因为没用 <nav>
当整个导航靠 <div class="header-nav"> 堆出来时,JS 里查元素得写 document.querySelector('.header-nav'),CSS 里样式规则绑定在类名上。一旦设计改版、类名重命名,所有依赖这个字符串的地方全崩——包括自动化测试里的 getByRole('navigation') 断言也会失效。
而换成 <nav>:
- JS 可直接用
document.querySelector('nav'),不依赖任何类名 - CSS 可写
nav a[aria-current="page"],语义即选择器 - 无障碍扫描工具(如 axe-core)能自动识别 landmark,CI 中报错即定位到结构层而非样式层
- 新成员打开 DevTools,一眼看出哪块是导航,不用翻 CSS 或 JS 注释猜意图
<main> 必须唯一且直系子元素,否则辅助工具和 Lighthouse 都会报错
常见错误是 CMS 模板里条件渲染漏判,比如页头组件和文章组件各自输出一个 <main>,最终 HTML 出现两个 <main>;或者把 <main> 嵌在 <header> 里——这等于告诉屏幕阅读器:“主内容藏在页眉里”,逻辑自相矛盾。
立即学习“前端免费学习笔记(深入)”;
后果很直接:
- Lighthouse 报
Multiple main landmarks - 辅助技术(如 NVDA)可能跳过第一个
<main>,用户无法一键聚焦真正主内容 - 搜索引擎降低页面可信度,影响富媒体摘要提取
- DevTools 的 Accessibility 面板标红,但错误位置指向 DOM 树顶层,排查时容易误判为 JS 注入问题
标题跳级(<h1> → <h3>)不是样式问题,是大纲断裂
动态渲染场景最危险:CMS 返回的富文本里自带 <h3>,前端 JS 直接 innerHTML 插入到已有 <h1> 的 <main> 中,结果文档大纲变成 <h1> → <h3>,中间缺了 <h2>。
这不是视觉错位,而是结构性损伤:
- 屏幕阅读器按 heading 层级跳转时,会把
<h3>当作新章节起点,忽略其上所有内容 - SEO 工具(如 Screaming Frog)无法构建正确内容树,导致关键词权重分散
- 构建时可用
remark-lint-heading-increment拦截 Markdown 渲染出的跳级 HTML,但纯 HTML 模板需靠 HTML validator 扫描 - 别用 CSS 把
<h2>改小字号假装是<h4>——语义和视觉必须一致,否则aria-level补救只是补丁,不是解法
<section> 和 <article> 的区别不在长度,在“能否独立分发”
很多人以为长内容用 <article>、短内容用 <section>,其实关键在于是否具备完整元信息和可复用性。
例如:
- 博客正文、新闻稿、用户评论 →
<article>(含<header>+<time>+ 作者信息,可被 RSS 抓取) - 文章里的“背景介绍”“技术原理”小节 →
<section>(主题明确但依赖上下文,无独立语义) - 整页商品列表包进一个
<section>是错的——每条商品都该是独立<article>,否则搜索引擎无法识别单个商品为独立实体
混淆这两者,会导致结构化数据(Schema.org)标记失败、语音助手无法准确播报单品信息、甚至 CMS 导出归档时丢失内容粒度。



















