只有当section是用户需键盘跳转、有独立功能意图且无更精确语义标签可用时,才显式设role="region";必须配具体aria-label或aria-labelledby,且内部须有可聚焦元素。

section加role="region"前先问自己:真需要吗?
绝大多数情况下,<section></section> 不该手动设 role="region"。它默认是 role="region" 吗?不是——<section></section> 默认没有地标角色(landmark),只是通用分组容器。但它也不等于“必须加 region 才有用”。只有当这个 <section></section> 在逻辑上是一个**用户需要键盘跳转、有独立功能意图的大区块**(比如“实时告警面板”“动态评论提交区”),且又无法用 <main></main>、<aside></aside> 等更精确的语义标签表达时,才考虑显式设 role="region"。
- 反例:把文章正文外层套个
<section></section>再加role="region"—— 正文本身应由<main></main>包裹,<section></section>仅用于其中可独立分发的子单元(如“背景介绍”“技术原理”) - 反例:纯样式布局用的
<section class="grid-row"></section>—— 这类容器没语义意图,用<div> 更干净 <li>正确信号:区块有明确标题(<code><h2></h2>)、内部含可聚焦控件(<input>、<button></button>)、且用户可能按 R 键(NVDA/JAWS)或 Ctrl+Alt+R(VoiceOver)直接跳入 - ❌ 错误:
<section role="region" aria-label=""></section>、<section role="region" aria-label="区域"></section> - ❌ 错误:
<section role="region" aria-label="订单模块"></section>—— “模块”是开发术语,非用户语言 - ✅ 正确:
<section role="region" aria-label="订单确认与支付表单"></section> - ✅ 正确:
<section role="region" aria-label="实时聊天窗口,当前客服:小李"></section> - 必须确保被引用的元素存在、未被
display: none或visibility: hidden隐藏(可用sr-only类隐藏但保留在无障碍树中) - 一个
role="region"只能有一个aria-labelledby值,不支持多个 ID(不像aria-describedby) - 不要为了用
aria-labelledby而硬加一个看不见的<h2></h2>—— 如果标题本就不存在,老实用aria-label - 确保区域内至少有一个默认可聚焦控件;若没有(比如纯展示卡片流),需为关键容器手动加
tabindex="0" - 避免在
<section role="region"></section>上直接设tabindex="-1"—— 这会让键盘用户根本无法导航到它 - 如果是模态弹窗类
<section></section>,JS 打开后必须立即调用.focus()移入焦点,关闭后恢复原焦点点
aria-label 必须写具体用途,不能留空或泛化
role="region" 本身无语义,不配 aria-label 或 aria-labelledby 就等于没写。屏幕阅读器只会读“区域”,甚至完全忽略该节点。更糟的是,如果写了空值或占位符,会触发可访问性检测工具报错(如 axe-core 报 aria-label must not be empty)。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
优先用 aria-labelledby 关联已有标题,别重复写文本
如果 <section></section> 内部已有可见标题(如 <h2 id="chat-title">在线客服</h2>),直接用 aria-labelledby="chat-title"。这比 aria-label 更可靠:视觉和语音文本一致,维护成本低,也避免因样式变更导致 aria-label 和实际内容脱节。
加了 role="region" 后,焦点必须能真正进去
仅设 role="region" + aria-label 不等于可访问。用户按 R 键能定位到该区域,但若内部没有可聚焦元素(如 <button></button>、<input>、或带 tabindex="0" 的容器),焦点会卡住或跳过,整个区域形同虚设。
aria-label,却忘了里面连一个可 tab 的按钮都没有。结果屏幕阅读器用户听到了“订单确认与支付表单”,按 Enter 却毫无反应——那不是辅助功能,是幻觉。










