屏幕阅读器依赖DOM直接子节点级地标语义,main必须是body直系子元素,否则无法识别为主内容区;标题层级断裂、nav被包裹、lang属性错误均会导致语义链断裂。

文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
为什么不能嵌套在里
屏幕阅读器会直接跳过被包裹的,当成普通区块处理。它依赖的是 DOM 树中的直接子节点级地标(landmark),一旦被、或包住,语义就断裂了。main必须是的直系子元素,否则 NVDA、VoiceOver 等工具无法将其识别为“主内容区”。
常见错误包括:React 组件封装时把main塞进Layout组件的div壳里;CSS Grid 布局用div.container包裹整个页面结构;服务端模板里统一套了<div id="app"></div>再渲染内容。
- 检查 DevTools 的 Accessibility 面板 → Landmarks 节点,确认是否只出现一个
main且 role 为 “main”
- 用
document.querySelector('body > main')验证是否为直接子节点
- 若必须用布局容器,让该容器不参与语义结构——用
div而非section,且不加role
标题层级断裂会让阅读障碍者“掉层”
不是样式问题,而是逻辑塌方。当
后面直接跟,中间缺,屏幕阅读器用户按 H 键跳转时会误判章节结束,直接跳到下一个,漏掉整块内容。这种断裂比视觉错位更致命。
真实场景里,它常来自:CSS 隐藏了某个标题但没删 DOM;JS 动态插入内容时没校验层级;UI 组件库默认用
作卡片标题,而卡片又放在主区域下,导致 H2→H2。
立即学习“前端免费学习笔记(深入)”;
- 每个
section必须以h2–h6开头,否则会被跳过
- 避免用
display: none隐藏标题——要删 DOM 或改用aria-hidden="true" + tabindex="-1"
- 用 axe 浏览器插件扫描,关注 “Heading order” 类错误
导航必须独立于视觉容器存在
nav被包在div.header-wrapper或ul里,等于主动屏蔽语义。屏幕阅读器读不出“导航”,只读“一段内容”。这不是 aria-label 能补救的——父容器中断了地标传播链。
尤其注意响应式菜单:很多方案用 JS 切换ul显隐,却忘了nav本身得始终在 DOM 顶层,且内部第一个可聚焦元素(如第一个a或button)必须在展开后立即获得焦点。
-
nav必须是body或main的兄弟节点,不能是子节点
- 多个导航区必须区分:
nav aria-label="主导航"、nav aria-label="页内目录"
- 折叠菜单展开后,调用
firstLink.focus(),别只改aria-expanded
lang属性写错等于让屏幕阅读器“说外语”
写lang="zh"或lang="ch",NVDA 就可能把中文读成日语或韩语,分词错乱、语调诡异。这不是小众问题——主流 AT 对 IETF 语言标签极其敏感。
正确值只有lang="zh-CN"(简体)、lang="zh-TW"(繁体)、lang="zh-HK"(港澳)。多语言段落需局部声明,比如英文引文:<p lang="en">...。
-
html标签上必须声明,meta或某段文字里补无效
- SSR 或静态生成阶段就要固化,别靠 JS 动态设置
- React/Vue 中用
dangerouslySetInnerHTML插入 HTML 时,确保含正确lang
真正难的不是写对单个标签,而是让整个结构链条不断裂:从html[lang]开始,到body下并列的header/main/footer,再到main里每个section都带标题、每个nav都不被包裹——任何一环脱节,阅读障碍者就会在语义路标上迷路。
屏幕阅读器会直接跳过被包裹的 常见错误包括:React 组件封装时把 不是样式问题,而是逻辑塌方。当 真实场景里,它常来自:CSS 隐藏了某个标题但没删 DOM;JS 动态插入内容时没校验层级;UI 组件库默认用 立即学习“前端免费学习笔记(深入)”; 尤其注意响应式菜单:很多方案用 JS 切换 写 正确值只有 真正难的不是写对单个标签,而是让整个结构链条不断裂:从包住,语义就断裂了。
main必须是的直系子元素,否则 NVDA、VoiceOver 等工具无法将其识别为“主内容区”。
main塞进Layout组件的div壳里;CSS Grid 布局用div.container包裹整个页面结构;服务端模板里统一套了<div id="app"></div>再渲染内容。
main且 role 为 “main”document.querySelector('body > main')验证是否为直接子节点div而非section,且不加role
标题层级断裂会让阅读障碍者“掉层”
后面直接跟
,中间缺
,屏幕阅读器用户按 H 键跳转时会误判章节结束,直接跳到下一个
,漏掉整块内容。这种断裂比视觉错位更致命。
作卡片标题,而卡片又放在
主区域下,导致 H2→H2。
section必须以h2–h6开头,否则会被跳过display: none隐藏标题——要删 DOM 或改用aria-hidden="true" + tabindex="-1"
导航必须独立于视觉容器存在
nav被包在div.header-wrapper或ul里,等于主动屏蔽语义。屏幕阅读器读不出“导航”,只读“一段内容”。这不是 aria-label 能补救的——父容器中断了地标传播链。ul显隐,却忘了nav本身得始终在 DOM 顶层,且内部第一个可聚焦元素(如第一个a或button)必须在展开后立即获得焦点。
nav必须是body或main的兄弟节点,不能是子节点nav aria-label="主导航"、nav aria-label="页内目录"
firstLink.focus(),别只改aria-expanded
lang属性写错等于让屏幕阅读器“说外语”
lang="zh"或lang="ch",NVDA 就可能把中文读成日语或韩语,分词错乱、语调诡异。这不是小众问题——主流 AT 对 IETF 语言标签极其敏感。lang="zh-CN"(简体)、lang="zh-TW"(繁体)、lang="zh-HK"(港澳)。多语言段落需局部声明,比如英文引文:<p lang="en">...。
html标签上必须声明,meta或某段文字里补无效dangerouslySetInnerHTML插入 HTML 时,确保含正确lang
html[lang]开始,到body下并列的header/main/footer,再到main里每个section都带标题、每个nav都不被包裹——任何一环脱节,阅读障碍者就会在语义路标上迷路。


















