语义标签本身不提供重用性,但它是组件可复用的必要前提;article、nav、main等原生标签承载结构契约,确保无障碍、seo与跨项目协作稳定,错用div会导致持续掉血。

直接说结论:语义标签本身不提供重用性,但它是组件可复用的必要前提——没有语义结构的组件,哪怕封装得再“模块化”,在无障碍、SEO、团队协作层面都会持续掉血。
为什么 div 封装的“组件”根本不算真正可复用
很多人把一堆 div class="card"> + CSS + JS 打包成“组件库”,结果发现:换个项目就要改 class 名、加 ARIA、手动补 role、测试时屏幕阅读器跳不过去。问题不在打包方式,而在起点就错了。
真正可复用的组件,必须自带结构契约。比如一个产品卡片,它天然是独立内容单元,那外层就该是 article,不是 div;里面有标题和描述,就该用 h3 + p,而不是 div class="title"。
-
article告诉浏览器:“这段内容可被 RSS 抓取、可被搜索引擎单独索引” -
nav告诉辅助技术:“这里是一组导航链接,允许用户一键跳转” -
main告诉爬虫和阅读器:“这是页面唯一主体,别在别的地方重复标记”
这些不是锦上添花,而是组件能跨项目、跨团队、跨设备稳定工作的底层协议。
哪些语义标签适合做组件外层容器
选错外层标签,等于给组件埋雷。关键看内容是否“自包含”和“可分发”:
- 博客文章、用户评论、商品卡片 → 用
article(必须有明确主题,建议含header或h2以上标题) - 服务流程、关于我们、常见问题 → 用
section(强调逻辑分组,但不独立分发) - 侧边栏广告、作者简介、相关链接 → 用
aside(与主内容相关但非主线) - 图文组合(如图表+说明、代码块+注释)→ 用
figure+figcaption,不是div包图
特别注意:main 和 header 不适合做组件外层——它们是页面级语义角色,一个页面只能有一个 main,header 必须对应其父级上下文(比如 article 内的 header 是文章头,不是页面头)。
Custom Elements 怎么和语义标签配合才不翻车
用 Web Components 封装时,最容易犯的错是:在 Shadow DOM 里塞一堆 div,再靠 aria-label 补救。这等于放弃语义,又想拿无障碍成果。
正确做法是把语义结构“透传”进 Shadow DOM,或由使用者决定:
- 如果组件本质是卡片,注册为
<product-card></product-card>,内部模板用<article><slot name="title"></slot><slot name="content"></slot></article> - 避免在自定义元素内部硬写
<div role="article">——<code>role只是降级兜底,不能替代原生语义 - 对外暴露
slot时,明确命名语义用途(如slot="header"、slot="footer"),而不是slot="top"或slot="box" - 若需样式隔离,Shadow DOM 内仍可用
article、figure等标签,它们在 Shadow 中依然保有语义 -
main不能出现在article、section、aside内部——它只属于整个页面 -
footer必须紧贴其归属容器(body、article、section),不能“悬空”在中间 -
nav内部必须有语义化列表结构,至少含ul/ol或带role="list"的容器 - 所有交互元素(按钮、链接)必须用原生
button/a,不用div+click事件模拟
嵌套规则和可访问性陷阱
语义标签之间有隐含的嵌套契约,违反它不会让页面崩,但会让自动化测试失败、阅读器行为异常:
最常被忽略的是标题层级连续性:组件内 h3 的出现,必须基于其所在上下文的标题等级。如果父级是 section 且已有 h2,那组件内就该用 h3;如果组件被用在 article 里且 article 自带 h1,那组件内标题就得从 h2 开始——这个逻辑无法靠 class 控制,只能靠结构推导。











