真正有效的html分段必须满足结构可读、内容可加载、语义对齐三要素:main须为body直接子元素且唯一,section必须带h2+标题,流式解析需状态缓存防标签断裂,否则分块加载仅视觉有效而丧失辅助技术支持。

大段 HTML 文本不能靠 <p></p> 硬切,也不能用多个 <div> 堆砌——这样既破坏屏幕阅读器导航逻辑,又让分块加载失去语义锚点。真正有效的分段,必须同时满足:结构可被读屏器识别、内容能按需加载、段落边界与语义层级对齐。
<h3>为什么<main>缺失会导致分段加载失效</main>
</h3>
<p>屏幕阅读器(如 NVDA、VoiceOver)默认把 <code><main></main> 当作正文唯一入口。没有它,或存在多个 <main></main>,读屏器会退回到逐个扫描 <h1></h1>~<h6></h6>,甚至从页眉开始朗读。此时你做的“分段加载”只是视觉上拆开了,辅助技术用户根本感知不到段落边界,更无法用 M 键跳转到主内容。
-
<main></main>必须是的直接子元素,不能被<div class="container"> 包裹 <li>一个页面只能有一个 <code><main></main>;SSR 框架中常见布局组件和页面组件各自 render 一个,需手动合并或剔除冗余 -
<main></main>内部第一级标题必须是<h2></h2>或更高(<h1></h1>应留给<header></header>),否则读屏器报“无标题内容”并跳过整块 - 错误写法:
<div class="chapter"><p>…</p></div>→ 读屏器不识别章节,也无法提取元数据 - 正确写法:
<section id="intro"><h2>引言</h2> <p>…</p></section>→ 支持 M 键跳转 + 自动注入metadata={'Header 2': '引言'} - 避免嵌套
<section></section>:子级内容应降级用<article></article>或<aside></aside>,否则大纲树断裂 - 使用
stopNodes: ['section']配置XMLParser,只监听<section></section>起止事件,避免误拆内部标签 - 每次
parser.parse(text)前检查当前是否处于未闭合的<section></section>中,若在中间则暂存 buffer,等下一块补全再触发onElement - 禁止用
split('\n')或正则匹配切 HTML 字符串——<p></p>内可能含换行,<pre class="brush:php;toolbar:false;"></pre>会彻底乱套 - 每个
<p></p>设置margin-bottom: 1.5em(相对字体大小),确保视觉呼吸感 - 在
<section></section>级别加aria-labelledby指向其<h2></h2>,读屏器朗读完标题后自动停顿 - 禁用
text-indent做段首缩进——屏幕阅读器不读空格,且影响 RTL 语言排版
用替代实现语义化分段
<section></section> 不是视觉容器,而是逻辑单元标识符。每个 <section></section> 应有明确主题,且必须带标题(<h2></h2> 或更高),否则会被读屏器忽略为普通 <div>。LangChain 的 <code>HTMLSectionSplitter 就依赖这个规则做结构感知分割。
分块加载时如何保留语义上下文
流式加载(如 ReadableStream + XMLParser)容易把 HTML 切成碎片,导致 <section></section> 开始标签和结束标签落在不同 chunk,解析失败或语义丢失。必须在 parser 层做状态缓存,而非简单按字符切分。
移动端与读屏器共用的段落间距控制
仅靠 margin-bottom 分隔段落,在读屏器中不产生语音停顿;而单纯加 <hr> 又破坏语义。真正起作用的是:视觉间距 + 语义边界 + 语音节奏三者同步。
最常被忽略的一点:分段不是为了“看起来分开了”,而是为了让机器和人都能按同一套逻辑理解内容边界。一旦 <section></section> 没标题、<main></main> 被包在 <div> 里、或流式 parser 没做标签状态跟踪,所有分块加载和阅读器适配就退化成徒劳的视觉优化。</div>
<section></section> 不是视觉容器,而是逻辑单元标识符。每个 <section></section> 应有明确主题,且必须带标题(<h2></h2> 或更高),否则会被读屏器忽略为普通 <div>。LangChain 的 <code>HTMLSectionSplitter 就依赖这个规则做结构感知分割。
分块加载时如何保留语义上下文
流式加载(如 ReadableStream + XMLParser)容易把 HTML 切成碎片,导致 <section></section> 开始标签和结束标签落在不同 chunk,解析失败或语义丢失。必须在 parser 层做状态缓存,而非简单按字符切分。
移动端与读屏器共用的段落间距控制
仅靠 margin-bottom 分隔段落,在读屏器中不产生语音停顿;而单纯加 <hr> 又破坏语义。真正起作用的是:视觉间距 + 语义边界 + 语音节奏三者同步。
最常被忽略的一点:分段不是为了“看起来分开了”,而是为了让机器和人都能按同一套逻辑理解内容边界。一旦 <section></section> 没标题、<main></main> 被包在 <div> 里、或流式 parser 没做标签状态跟踪,所有分块加载和阅读器适配就退化成徒劳的视觉优化。</div>











