90%长文章可访问性差源于大纲断裂和目录锚点失效,修复需正确使用与标签,并确保标题有合法id且严格嵌套层级。

长文章可访问性差,90% 是因为大纲断裂 + 目录锚点失效,不是样式或 JS 问题。修复核心就两条:用对 <section></section> 和 <main></main>,再让每个标题有合法 id 并严格嵌套层级。
为什么 Chrome 的「Document Outline」里一堆空节点或跳级标题
浏览器大纲算法只认 <h1></h1>–<h6></h6> 的实际嵌套顺序,不看 class、不看视觉缩进、不看 CSS 隐藏状态。常见断裂点:
-
<h1></h1>后直接出现<h3></h3>:大纲会把<h3></h3>当作新章节起点,跳过逻辑中间层 - 页眉、侧边栏、页脚里塞了
<h2></h2>:这些标题被计入全局大纲,污染主内容结构 - 用
<div class="h2"> 模拟标题:完全不参与大纲解析,工具检测为“无标题” <li> <code><main></main>嵌套在<div id="app"> 里:它不再是 <code>直系子元素,屏幕阅读器忽略其地标角色怎么用
修复子大纲但不污染全局结构 <section></section>是唯一能重置内部标题层级的原生标签。它本身不生成大纲节点,但能让<h2></h2>–<h6></h6>在其内部自成子单元。- 错误写法:
<h1>实验报告</h1> <h2>方法</h2> <h3>样本采集</h3>→<h3></h3>被判跳级 - 正确写法:
<h1>实验报告</h1> <section><h2>方法</h2> <h3>样本采集</h3></section>→<h3></h3>成为<h2></h2>的合法子节 - 每个
<section></section>必须含且仅含一个<h2></h2>–<h6></h6>,不能只有<p></p>或<div> <li>避免三层嵌套:<code><section><section><section></section></section></section>容易让辅助技术用户迷失,两层(主节 + 子节)足够 - ID 值含空格或中文(如
id="第二章")→ 浏览器可能拒绝解析,必须转为id="di-er-zhang"这类纯 ASCII 字符 - 多个标题生成相同 ID(如都叫
introduction)→ 只有第一个生效,后续点击全部跳到同一处 - 目录 JS 执行太早:标题在 Markdown 渲染或 React 组件挂载后才出现,
querySelectorAll('h2, h3')扫不到 → 改用MutationObserver监听目标容器变化 - 别依赖
title属性补 ID:<h2 title="方法"></h2>不触发锚点跳转,id才是唯一依据 - 全页面只能有一个
<main></main>,且必须是的直系子元素 -
<main></main>内不能混入广告位、推荐卡片、客服入口 —— 这些该放<aside></aside>或<footer></footer> - 动态渲染内容(如分页加载)必须确保新区块插入时,仍处于同一
<main></main>下,不能每次加载都新建一个 - 检查方式:控制台执行
document.body.children,输出列表中<main></main>应为其中之一,且不能被任何<div> 包裹 </div>
目录锚点点击无效?先检查这三件事
JS 自动生成目录时,锚点失效几乎都出在 ID 层面,和滚动逻辑无关。
最容易被忽略的:
不只是个容器 <main></main>是屏幕阅读器按 M 键跳转的唯一锚点,它的位置和内容边界直接影响残障用户能否 3 秒内触达正文。 - 错误写法:











