语义化标签需按内容意图精准使用:仅一个且不可嵌套;须含标题并构成主题分组;必有alt、须关联表单控件、不可用替代;标题层级必须连续递进。

直接说结论:语义化标签不是“用了就对”,而是“用对才有效”。多数问题出在标签被当成视觉分组工具,而非内容意图表达手段。
为什么只能有一个,且不能嵌套在布局组件里
多个 <main></main> 会让屏幕阅读器(如 NVDA、JAWS)在按 M 键跳转时只识别第一个,后续的被跳过或触发错误导航逻辑。这不是渲染问题,而是可访问性树构建阶段的语义冲突。
- Next.js 或 Remix 的
Layout组件里写了<main></main>,子页面又包一层<main></main>—— 这是典型冗余 - SSR 渲染时服务端注入一个
<main></main>,客户端 hydration 又挂载一个 —— DOM 中实际存在两个,辅助技术无法区分主次 - 解决办法:只在真正承载页面核心内容的最内层容器用
<main></main>;布局壳、头部、侧边栏一律用<header></header>、<nav></nav>、<aside></aside>
什么时候该用,什么时候必须用
<section></section> 不是“看起来像一块内容”的视觉标签,而是有明确语义门槛的结构单元:它必须有自己独立的 <h2></h2>–<h6></h6> 标题,且内容能构成一个主题分组(比如“技术参数”“用户评价汇总”)。
- 错误示例:
<section><p>欢迎关注我们</p></section> —— 没标题、不可分发、无结构价值
- 正确场景:一个带
<h3>售后服务说明</h3> 的区块,内部含多段描述和列表
- 纯样式容器(如 Flex 包裹卡片)、动态组件外壳(React/Vue 封装的弹窗、骨架屏)、ARIA 区域包装器 —— 这些都该用
<div>,强行套 <code><section></section> 反而稀释语义浓度
图片、表单、按钮的“伪语义”比无语义更危险
加了 title 属性、CSS 对齐 label、用 <div onclick> 模拟按钮,这类写法看似“差不多”,实则破坏可访问性链路,还引入 JS 补丁维护成本。
<ul>
<li>
<code><img> 必须带 alt 属性;title 不被所有读屏支持,且仅悬停可见,对键盘/语音用户无效
-
<input> 和关联文本必须用 <label for="id"></label> 或嵌套写法;仅靠 CSS 视觉对齐,focus 时读屏听不到上下文
- 用
<div onclick="submit()"> 替代 <code><button></button>,需手动补 role="button" tabindex="0" aria-label;原生 <button></button> 自带焦点管理、空格/回车触发、禁用状态语义
标题层级断裂比标签用错更隐蔽也更致命
这是最容易被忽略的问题:用 <h1></h1> 开头,接着跳到 <h3></h3>,中间缺 <h2></h2>;或者同一层级连续多个 <h2></h2> 却没有逻辑分组。屏幕阅读器依赖标题树导航,断裂会导致用户无法建立内容地图。
检查方式很简单:打开浏览器开发者工具 → 元素面板 → 查看 <h1></h1> 到 <h6></h6> 是否逐级递进、无跳跃、无缺失。不要依赖视觉样式判断层级,<h2></h2> 可以用 CSS 显示得比 <h3></h3> 小,但语义上它仍是二级标题。
<section></section> 不是“看起来像一块内容”的视觉标签,而是有明确语义门槛的结构单元:它必须有自己独立的 <h2></h2>–<h6></h6> 标题,且内容能构成一个主题分组(比如“技术参数”“用户评价汇总”)。
- 错误示例:
<section><p>欢迎关注我们</p></section>—— 没标题、不可分发、无结构价值 - 正确场景:一个带
<h3>售后服务说明</h3>的区块,内部含多段描述和列表 - 纯样式容器(如 Flex 包裹卡片)、动态组件外壳(React/Vue 封装的弹窗、骨架屏)、ARIA 区域包装器 —— 这些都该用
<div>,强行套 <code><section></section>反而稀释语义浓度图片、表单、按钮的“伪语义”比无语义更危险
加了
title属性、CSS 对齐 label、用<div onclick> 模拟按钮,这类写法看似“差不多”,实则破坏可访问性链路,还引入 JS 补丁维护成本。 <ul> <li> <code><img>必须带alt属性;title不被所有读屏支持,且仅悬停可见,对键盘/语音用户无效 -
<input>和关联文本必须用<label for="id"></label>或嵌套写法;仅靠 CSS 视觉对齐,focus 时读屏听不到上下文 - 用
<div onclick="submit()"> 替代 <code><button></button>,需手动补role="button" tabindex="0" aria-label;原生<button></button>自带焦点管理、空格/回车触发、禁用状态语义标题层级断裂比标签用错更隐蔽也更致命
这是最容易被忽略的问题:用
<h1></h1>开头,接着跳到<h3></h3>,中间缺<h2></h2>;或者同一层级连续多个<h2></h2>却没有逻辑分组。屏幕阅读器依赖标题树导航,断裂会导致用户无法建立内容地图。检查方式很简单:打开浏览器开发者工具 → 元素面板 → 查看
<h1></h1>到<h6></h6>是否逐级递进、无跳跃、无缺失。不要依赖视觉样式判断层级,<h2></h2>可以用 CSS 显示得比<h3></h3>小,但语义上它仍是二级标题。











