必须唯一且不得嵌套于其他语义容器内,和需依内容功能而非视觉布局使用,语义标签通过隐式ARIA角色与DOM约束保障可访问性、SEO及JS定位可靠性。

<main></main> 必须唯一、<header></header> 不能当装饰盒、<section></section> 不是视觉格子——这些不是规范教条,而是浏览器解析 DOM 时的真实约束条件。语义化标签让结构“稳固”,本质是让 DOM 树可预测、可定位、不可绕过。
DOM 层级被语义标签硬性锚定
浏览器解析 HTML 时,<main></main>、<nav></nav>、<article></article> 这类标签会强制生成特定的隐式 ARIA 角色和 outline 行为,同时限制嵌套关系。比如:
-
<main></main>在整个文档中只能出现一次,且不能是<header></header>、<footer></footer>、<nav></nav>、<section></section>的子元素 —— 浏览器会直接忽略嵌套的第二个<main></main>,或静默降级为<div> <li> <code><article></article>内部可以有独立的<header></header>、<footer></footer>,但<section></section>没有这种自治权;它必须依附于上层语义容器(如<main></main>或<article></article>)才有意义 - 用
<div class="main"> 替代 <code><main></main>,JS 中document.querySelector('main')就会返回null,哪怕 CSS 样式完全一致结构断裂常发生在动态操作之后
很多“上线后结构突然失效”的问题,根源不在初始 HTML,而在 JS 操作阶段。例如:
Wechat Article Html下载将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 用
innerHTML = '...'覆盖整个<main></main>内容,会连带抹除其语义边界,新插入的 HTML 若没重写语义标签,DOM 就退化成一堆<div> <li>SPA 路由切换时,若只替换 <code><main></main>的子节点但未调用replaceChildren()或重建语义包裹,旧的<article></article>可能残留,新的内容却裸奔在<main></main>下 - 构建工具(如
html-webpack-plugin)自动注入 wrapper<div id="app">,若开发者没注意它把 <code><main></main>包进去了,就等于违反了“<main></main>不得嵌套在<div> 中”的契约 <h3>标题层级错乱会让整个骨架脱钩</h3> <p><code><h1></h1>到<h6></h6>不是字号开关,而是 DOM 中不可跳过的逻辑链。搜索引擎和 VoiceOver 都靠它建立导航路径:- 跳级(
<h2></h2>后直接<h4></h4>)、重复<h1></h1>、或把标题塞进<div> 再用 CSS 模拟,都会导致大纲(outline)断裂 <li>Lighthouse 报 “Heading elements do not appear in a sequentially-descending order”,往往不是样式问题,而是结构已失联</li> <li> <code><article></article>内部的<h2></h2>是它的局部起始,不与外部<h1></h1>比较层级;但若把它放在<main></main>外、又没包在<section></section>或其他语义容器里,它就失去上下文,变成孤点
真正容易被忽略的,是语义标签之间的“契约关系”:它们不是独立存在,而是一组相互校验的 DOM 约束。一旦某处松动(比如用
<div class="nav"> 冒充 <code><nav></nav>),后续所有依赖这个结构的 JS、CSS、辅助技术都会开始漂移——不是立刻报错,而是缓慢失准。 - 跳级(
- 用










