标签页切换必须用button实现并同步aria-selected、aria-controls等属性,内容区需设role="tabpanel"和aria-hidden,支持方向键导航及初始状态即时同步。

标签页切换对屏幕阅读器用户来说,不是“点一下就换”,而是需要明确当前在哪、能跳到哪、内容是否已加载——没做语义和状态同步,等于把人关在黑盒里。
tab 切换必须用 button 而不是 div 或 span
读屏器只识别原生可聚焦、可交互的元素。div 加 onclick 或 tabindex="0" 无法触发标准键盘行为(如空格/回车激活),且不会被归类为“控件”。
- 正确写法:
-
role="tab"告诉读屏器这是标签页项,不是普通按钮 -
aria-selected必须实时同步:激活时为"true",非激活时为"false"(不能省略或留空) -
aria-controls的值必须严格匹配对应内容区的id,比如指向内容区要用
tabpanel+role="tabpanel"显式声明仅靠
display: none或hidden隐藏内容,会让屏幕阅读器直接跳过整个区域——它感知不到“这里本该有东西”。
DeepBI DHTML 页面生成器下载生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 每个内容区必须加
role="tabpanel",并设id与标签页的aria-controls对应 - 非激活内容区设
aria-hidden="true";激活的设为"false"(不能省略) - 不要用
display: none替代aria-hidden:前者从可访问树中移除,后者保留结构但隐藏呈现 - 若内容动态加载,首次展示前需确保
aria-busy="true",加载完成后移除并设aria-live="polite"播报更新
键盘导航必须支持 Tab / 方向键 / Home / End
仅靠鼠标点击,等于默认放弃键盘用户。焦点流断裂或方向键无响应,是标签页无障碍最常被忽略的一环。
- 所有
role="tab"元素必须在同一tabindex顺序中,不能分散在不同容器里 - 用
ArrowLeft/ArrowRight(水平布局)或ArrowUp/ArrowDown(垂直)切换激活项,并同步更新aria-selected和焦点 -
Home键跳转第一个 tab,End键跳转最后一个 - 切换后,焦点必须落在对应
tabpanel内首个可聚焦元素上(如标题、输入框),不能停在空白区域
多个标签页组共存时,
tablist容器必须带aria-label页面里有主导航、筛选栏、详情页内嵌 tab —— 全部用
?读屏器只会报“标签列表”,完全分不清哪个是哪个。- 必须用 这类具体描述,而非
"Tab list"或空值- 避免多个
tablist共用相同aria-label,否则键盘用户按 D 键跳转时无法区分- 不要把
tablist套在里:两者语义冲突,nav是地标(landmark),tablist是控件组,混用会导致焦点逻辑错乱最容易被跳过的其实是初始状态同步:页面加载后,
aria-selected、aria-hidden、焦点位置、aria-live的启用时机,必须在 DOM 就绪后立刻完成,而不是等 JS 绑定完事件才补。延迟哪怕 200ms,键盘用户就已经开始按 Tab 往下找了。 - 避免多个
- 每个内容区必须加
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










