HTML语义标签有严格内容模型限制:<header>/<footer>非万能容器,<main>唯一且不可嵌套,<section>须有标题,<p>内禁用块级元素,否则DOM被浏览器重写。

<header> 和 <footer> 不能当“万能容器”用,<main> 只能出现一次且不能嵌套,<section> 没标题就是无效语义——这些不是建议,是浏览器解析时会直接重写 DOM 的硬性限制。
为什么 <p> 里塞 <div> 会导致 CSS 和 JS 失效
浏览器把 <p> 当作短语级容器,只允许行内容(<span>、<strong>、<img> 等)。一旦遇到 <div> 或 <ul>,它会立刻闭合当前 <p>,再把非法子元素放到外面。
- 你在源码写
<p><div>文字</div></p>,Elements 面板里实际看到的是<p></p><div>文字</div> -
p > div这类 CSS 选择器永远不匹配 -
document.querySelector('p').children返回空的HTMLCollection - 想包裹多段内容或加标题?换用
<section>或<article>,别硬撑<p>
<nav> 和 <header> 为什么不能互相嵌套
<header> 的语义是“某个节区的页眉”,只该放与当前上下文直接相关的元信息:标题、logo、简短说明文字。它不是页面顶部的视觉容器。
- 错误:
<header><nav><ul>...</ul></nav></header>—— 浏览器不会报错,但会破坏大纲层级,屏幕阅读器可能跳过导航或误读结构 - 正确做法:让
<nav>和<header>并列,或一起包在<section>里,各自保持语义独立 -
<nav>本身也禁止塞<form>、<main>或另一个<nav>;它只承载导航链接组 - 面包屑、分页、筛选栏不算主导航,建议用
<nav aria-label="breadcrumb">显式标注
<section> 和 <article> 的标题不是可选项
没有标题的 <section> 对辅助技术来说等于不存在;<article> 缺少 <h2>~<h6> 会让 RSS 订阅、分享卡片丢失上下文。
立即学习“前端免费学习笔记(深入)”;
-
<section><p>一段描述</p></section>→ 不如直接用<div>,加标题才激活语义 -
<article>必须满足“可独立分发”:复制整块 HTML 到邮件或 RSS 阅读器里,仍能被识别为一篇完整文章 -
<section>是逻辑分组,<article>是内容单元;一个博客列表页,每个条目用<article>,整个列表用<section>包裹 - 用浏览器的 Accessibility 面板检查大纲树:如果
<article>下没标题,或标题跳级(比如<h3>直接跟在<h1>后),屏幕阅读器会困惑
<main> 的唯一性和嵌套禁区
<main> 表达的是“本页唯一主内容”,这个约束是强制性的。浏览器和辅助技术都依赖它定位核心信息。
- 全页面只能有一个
<main>,且不能出现在<article>、<aside>、<nav>、<header>、<footer>内部 - 错误示例:
<article><main>正文</main></article>—— 这会让<main>的语义失效,搜索引擎可能忽略其中内容 - 嵌套
<main>不会报错,但 DOM 树中只会有一个被识别为有效主区域,其余被降级为普通<div> - 仪表盘、后台管理页等复杂布局中,若主内容区域不明确,宁可用
<div role="main">,也别强行拆分<main>
最常被忽略的一点:语义标签的合法性不取决于是否“看起来像”,而取决于是否符合 content model(内容模型)——也就是 W3C 规定的“它允许包含什么”。写对了,机器才能读懂;写错了,DOM 就已悄悄变形。



















