语义化标签 section article 区别
学完这篇,你能一眼判断出某块内容到底该用 <section>、<article> 还是老老实实用 <div>,不再靠感觉瞎选,也不会再写出「满屏 section 但一个标题都没有」的页面。
第一步:先记住一条判断标准,再去看细节
这一步要解决的问题是:别急着背定义,先用一句话把两者的分界线画出来。做完这步,你遇到 80% 的情况已经能直接下结论。
这条标准是:
- 能独立搬走吗?把这部分内容单独剪出来,放到 RSS 阅读器、微信推文、另一个网站的列表页里,它还读得通、还完整吗?能,就用
<article>。 - 它是一个有主题的分组吗?它是某篇内容里的一个小节,脱离上下文就读不懂,而且你能给它起一个有意义的标题吗?能,就用
<section>。 - 两个都不满足?那它只是为了布局、为了挂 class、为了做 flex 容器,用
<div>。
举个例子。一篇博客文章里的「评论区」,它整体上是一个有主题的分组(分组主题叫「评论」),所以外层是 <section> 加一个 <h2>评论</h2>;而里面每一条单独的评论,自己就能成立、能被单独转发,所以每条是 <article>。
第二步:认识 article,它到底「独立」到什么程度
这一步要明确 <article> 的边界,做完你就能判断哪些语义块该用它。
HTML 规范里对 <article> 的定义是:一个自包含的组合,意图是可以独立分发或复用(例如通过聚合订阅)。规范原文强调的是「independently distributable or reusable」。
符合这个描述的典型场景:
- 博客文章、新闻稿、论坛帖子
- 用户评论、留言
- 商品卡片、商品详情
- 一个独立的交互式小组件(比如天气小挂件)
- 报刊杂志里的一篇稿件
判定小技巧:**假设你把这个 <article> 从页面里抠出来,单独打开一个空白 HTML 文件放进它,它应该还是一篇能读的东西,而不是一堆没头没尾的碎片。** 论坛帖子符合,因为它自带标题、作者、时间、正文;而「首页顶部的轮播图区域」不符合,抠出去就是一堆图。
还有一个细节值得单独记住:
注意:
<article>内部的<header>和<footer>,属于这个 article 本身,而不是整个页面。也就是说,<article><footer>里写「本文标签:CSS、布局」是正确的;但如果你想写「版权所有 © 2024 某某公司」,那属于页面级 footer,不该塞进 article 里。
第三步:认识 section,它不是「高级版 div」
这一步要纠正最常见的误解。做完这步,你会知道什么时候用 section 反而比用 div 更糟。
规范的说法是:<section> 是文档或应用中的一个通用小节,是一个主题性分组,通常带标题(typically with a heading)。规范里还有一句明确警告:
The section element is not a generic container element. When an element is needed only for styling purposes or as a convenience for scripting, authors are encouraged to use the div element instead.
翻译过来就是:section 不是通用容器。只有为了样式或者为了方便脚本操作时,请用 div。
所以下面这种写法是错的:
<!-- 错误:section 被当成样式容器用了 -->
<section class="flex items-center gap-4">
<img src="logo.png" alt="Logo">
<button>立即购买</button>
</section>
<!-- 正确:它只是个布局容器,没有主题,用 div -->
<div class="flex items-center gap-4">
<img src="logo.png" alt="Logo">
<button>立即购买</button>
</div>
而正确的 section 长这样:
<section>
<h2>安装步骤</h2>
<p>先执行 npm init -y ……</p>
</section>
它能被起一个名字,这个名字就是它的 <h2>。
注意:如果一个「小节」你憋了半天也想不出该给它起什么标题,这通常是个信号——它根本不是一个主题分组,请改用
<div>。规范虽然没强制要求 section 必须有标题,但实践中一个没标题的 section 对屏幕阅读器用户几乎没有价值。
第四步:用四问决策法,逐个判定你的内容块
这一步给你一套可以反复套用的流程,做完后你面对任何一块 HTML 都能快速归类。
按顺序问自己四个问题,第一个答「是」的就是答案:
- 这块内容能被单独分发、单独阅读吗?→
<article> - 这块内容是一个有主题、能起标题的分组吗?→
<section> - 它是一个独立的、跟主内容相关但不属于主线的补充块吗?(侧边栏、广告、相关阅读)→
<aside> - 只是为了布局、样式、JS 挂载点?→
<div>
用这套流程过一遍真实页面:
| 内容块 | 判定 | 理由 |
|---|---|---|
| 一篇博客正文 | article | 可独立分发 |
| 正文里的「性能对比」小节 | section | 有标题的主题分组 |
| 右侧「热门文章」列表 | aside | 补充内容,不属于主线 |
| 用来做两栏布局的外层包裹 | div | 纯布局 |
| 每条读者评论 | article | 单条可独立阅读 |
| 评论区整体 | section | 主题「评论」,有标题 |
第五步:搞清楚嵌套关系,这才是最容易出错的地方
这一步解决嵌套场景。做完这步,你不会再把 article 和 section 的父子关系搞反。
两者可以互相嵌套,取决于语义,不是取决于谁「更大」。
article 套 section(文章内部划分小节):
<article>
<header>
<h1>用 CSS Grid 重写后台表格</h1>
<p>发布于 <time datetime="2024-03-11">2024年3月11日</time></p>
</header>
<section>
<h2>为什么放弃 table 布局</h2>
<p>……</p>
</section>
<section>
<h2>改造成本</h2>
<p>……</p>
</section>
<footer>
<p>本文标签:CSS、布局</p>
</footer>
</article>
section 套 article(一个「最新文章」聚合区里放多篇独立文章):
<section aria-labelledby="latest-posts">
<h2 id="latest-posts">最新文章</h2>
<article>
<h3><a href="/post-1">Vite 冷启动为什么快</a></h3>
<p>摘要……</p>
</article>
<article>
<h3><a href="/post-2">Webpack 5 的持久化缓存</a></h3>
<p>摘要……</p>
</article>
</section>
article 套 article(文章里嵌评论):
<article>
<h1>如何选择前端构建工具</h1>
<p>……正文……</p>
<section>
<h2>读者评论</h2>
<article>
<h3>老王</h3>
<p>Vite 的冷启动确实快,我们小项目已经全换过去了。</p>
</article>
<article>
<h3>小李</h3>
<p>我们是单体仓库,还在用 webpack 5,迁移成本太高。</p>
</article>
</section>
</article>
注意这里标题层级:文章的 <h1>、评论区的 <h2>、每条评论作者的 <h3>。嵌套语义块时,标题层级要跟着走,不要出现 article 里突然跳回 <h1> 的情况。
注意:网上很多老教程会告诉你「section 会自动生成文档大纲层级」。**这个 HTML5 大纲算法(outline algorithm)从来没有被主流浏览器和屏幕阅读器真正实现过**,现在已经被移出规范。别指望靠嵌套 section 生成层级结构,老老实实按顺序写
<h1>到<h6>。
第六步:避开五个高频坑
这一步把上面几条串成一份避雷清单。
坑一:用 section 包所有东西。 打开 DevTools 一看满屏 <section>,这是把 section 当 div 用了。判断口诀:没有标题,就不是 section。
坑二:用 article 包卡片列表的每一项。 这个其实是对的,商品卡片、文章卡片每张都能独立成立,用 article 没问题。但「卡片列表」这个外层容器不该用 article,它只是个分组,用 <section> 或者 <ul>。
坑三:section 没有可访问名称,却指望屏幕阅读器能跳转。 按现在的 ARIA in HTML 规范,<section> 只有在有「可访问名称」时才会被映射成 region 这个 landmark 角色。两种给名字的方式:
<!-- 方式一:aria-labelledby 指向标题 -->
<section aria-labelledby="s1">
<h2 id="s1">安装步骤</h2>
</section>
<!-- 方式二:aria-label 直接写 -->
<section aria-label="用户评价">
…
</section>
坑四:页面里出现多个 <main>。 <main> 是页面级唯一的主内容容器,<article> 里不要再套 <main>。article 表达「这是一篇独立内容」,main 表达「这是本页的主体」,两者层级不同。
坑五:为了 SEO 强行堆语义标签。 搜索引擎会读语义标签,但不会因为你把 div 改成 section 就给你加权。语义标签的第一受益方是用屏幕阅读器的人和半年后的你自己。
第七步:动手写一遍,用两个工具自查
这一步把知识变成肌肉记忆。做完你会得到一份可验证的语义化页面骨架。
原文链接:https://www.gj0.com/thread-1259.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。