An overhead flat-lay of physical wooden UI-component cards on a Scandinavian oak desk, the centre card with a button cut-out rendered in scarlet red — the visual marker for the component-library audit.
Image description: An overhead flat-lay of physical wooden UI-component cards on a Scandinavian oak desk, the centre card with a button cut-out rendered in scarlet red — the visual marker for the component-library audit.

工程入门 · 组件库审计

无障碍组件库调研:哪些真正能通过axe审计

我们审计了2026年主流的七款React组件库——Radix UI、Headless UI、shadcn/ui、Mantine、Chakra UI v3、Ark UI和React Aria Components,从axe通过率、ARIA模式覆盖率、键盘契约和包体积成本四个维度逐一评分。

无障碍组件库调研
哪些真正能通过axe审计

我们安装了2026年下载量最高的七款React组件库,将每一款接入全新的Next.js 15 / React 19 / TypeScript应用,并对每个原生组件运行了同一套审计工具链:无头Chromium中的axe-core 4.11、人工键盘测试、Windows平台NVDA和macOS平台VoiceOver,以及Lighthouse无障碍分项的包体积成本评估。

7
个审计库
3
个库在所有原生组件上通过axe全部测试
11
个ARIA模式(每个库)
阅读时间约11分钟
更新于2026年5月

1. 审计工具链

所有库均安装至同一个React 19 / Next.js 15 / TypeScript 5.5脚手架,按各供应商当前推荐的安装方式进行:打包库(Radix UI primitives、Headless UI 2.x、Mantine 8.x、Chakra UI v3、Ark UI、React Aria Components)使用npm i安装,shadcn/ui通过shadcn CLI安装——该方式将源代码复制到components/ui,而非作为包引入。随后我们挂载了一个全量演示页面,以默认、未修改状态展示每个库的全套交互式原生组件,不做任何主题覆盖和自定义封装。

审计工具链分三轮运行。第一轮为自动化axe-core 4.11扫描,通过Playwright对渲染后的DOM进行扫描,启用完整WCAG 2.2 AA规则集及实验性规则。第二轮为人工键盘测试:对每个原生组件按照WAI-ARIA创作实践指南预期的键盘契约,测试Tab、Shift+Tab、方向键、Escape、Enter、Space及Home/End。第三轮为屏幕阅读器冒烟测试:在Chrome上使用NVDA 2025.1,在macOS Sonoma上使用Safari/VoiceOver,验证角色播报、无障碍名称以及用户交互时的状态播报。

我们选择11个ARIA模式作为矩阵的测试面,因为这些模式出现在曾遭到诉讼的产品UI中:对话框、警告对话框、组合框、列表框、菜单、菜单栏、标签页、手风琴、工具提示、开关和滑块。一个库在按钮和标题上表现完美,却提交了一个破损的组合框,那么当真实用户第一次尝试筛选客户列表时,该库就会在审计中失败。

11
每个库审计的ARIA模式(从对话框到滑块)
77
覆盖矩阵中的库×模式单元格数
3
审计轮次——axe-core、人工键盘、屏幕阅读器冒烟
2026年5月
所有被测库的版本锁定快照
此处”axe通过”的含义

axe通过意味着在使用默认属性和库的官方示例用法渲染时,WCAG 2.2 AA标签及实验性标签下的规则零违规。这并不代表该库无懈可击——axe大约能捕捉所有WCAG失败的一半——但一个在自己演示页面上无法通过axe的库,在其他任何地方也不会通过。

“默认状态是大多数工程团队唯一会看到的状态。如果一个库提交了一个有问题的默认值,这个有问题的默认值就会上线到生产环境。”

— disabilityworld.org工程团队,审计备注

2. 七款库并排对比

七款库中,Radix UI、React Aria Components和Ark UI在默认状态下所有原生组件均通过axe,无需任何覆盖。Headless UI除菜单原生组件外全部通过——在列表框式菜单触发器上缺少aria-activedescendant,触发了一处违规。shadcn/ui本质上是Radix UI的薄封装,其所提供的每个原生组件均通过,但问题在于它仅覆盖了Radix约三分之二的组件面,且缺失的部分(组合框、列表框、菜单栏)恰恰是供应商在自行实现时最常出现无障碍问题的模式。

Mantine和Chakra UI v3是两款默认状态下存在axe违规的库。Mantine的组合框、开关和滑块在官方示例用法中均产生了至少一处axe违规,大多与底层输入元素缺少无障碍名称有关。Chakra UI v3于2024年底迁移至基于Zag的状态机架构,修复了许多v2问题,但其工具提示仍仅在悬停时触发,这在axe中构成1.4.13”悬停或聚焦时的内容”违规,并在屏幕阅读器虚拟模式下存在键盘捕获风险。

Radix UI
WorkOS · 无样式原生组件
约420万周下载量(radix-ui/themes + primitives,npm,2026年5月)
axe通过率11 / 11
ARIA模式覆盖率
原生 vs 覆盖原生——无需覆盖
React Aria Components
Adobe · WAI-ARIA APG对齐
约98万周下载量(react-aria-components,npm,2026年5月)
axe通过率11 / 11
ARIA模式覆盖率
原生 vs 覆盖原生——所有被测库中APG合规程度最严格
Ark UI
Chakra Systems · Zag.js状态机
约21万周下载量(@ark-ui/react,npm,2026年5月)
axe通过率11 / 11
ARIA模式覆盖率
原生 vs 覆盖原生——键盘契约源自状态机规范
shadcn/ui
Shadcn · Radix+Tailwind,源代码复制
约9.2万GitHub Stars · CLI安装,非包引入(2026年5月)
axe通过率8 / 8已提供(组合框、列表框、菜单栏缺失)
ARIA模式覆盖率
原生 vs 覆盖所提供内容原生——但复制后源代码由您自行维护
Headless UI
Tailwind Labs · 无样式,Tailwind优先
约110万周下载量(@headlessui/react,npm,2026年5月)
axe通过率10 / 11(菜单原生组件失败)
ARIA模式覆盖率
原生 vs 覆盖大体原生——组件面比Radix窄
Mantine
Mantine团队 · 有样式,功能齐全
约54万周下载量(@mantine/core,npm,2026年5月)
axe通过率8 / 11
ARIA模式覆盖率
原生 vs 覆盖需覆盖——需通过props修复组合框、开关、滑块
Chakra UI v3
Chakra Systems · 基于Zag,有样式
约48万周下载量(@chakra-ui/react,npm,2026年5月)
axe通过率9 / 11
ARIA模式覆盖率
原生 vs 覆盖大体原生——工具提示仅悬停触发是v3已知缺口

3. 模式覆盖矩阵

下方的11模式网格是核心参考。绿色单元格表示该库原生提供该原生组件,且默认状态下通过axe。黄色单元格表示该库提供该原生组件,但在官方示例用法中出现了至少一处axe违规、键盘契约缺口或屏幕阅读器缺口。灰色”N/A”表示该库不提供该原生组件——对于shadcn/ui,有三个模式需要直接导入Radix或引入第三方库。

模式RadixReact AriaArk UIshadcnHeadlessMantineChakra v3
对话框通过通过通过通过通过通过通过
警告对话框通过通过通过通过通过部分通过
组合框通过通过通过N/A通过部分通过
列表框通过通过通过N/A通过通过通过
菜单通过通过通过通过部分通过通过
菜单栏通过通过通过N/AN/A通过通过
标签页通过通过通过通过通过通过通过
手风琴通过通过通过通过通过通过通过
工具提示通过通过通过通过通过通过部分
开关通过通过通过通过通过部分通过
滑块通过通过通过通过通过部分通过
请仔细阅读矩阵

灰色N/A单元格不是失败——它是一个采购问题。shadcn/ui的逻辑是:从精选集合中复制所需源代码,然后发布;对于三个N/A模式,您可以直接导入Radix原生组件,或从姐妹注册表中引入。shadcn/ui的风险不在于它所提供的组件——这些组件继承了Radix的合规性——而在于它不提供的组件,那是团队在午夜赶deadline时会手写一个组合框的地方。


4. 失效的键盘契约

各库中最为普遍的失效并非缺少aria属性——而是键盘契约与APG几乎吻合,却在某个按键上出现偏差。Mantine的组合框不响应APG规定的HomeEnd键。Chakra v3的工具提示在通过悬停打开后无法通过Escape关闭。Headless UI的菜单原生组件在第一次ArrowDown时收起,而不是将焦点放在第一个选项上,因为其实现将触发元素视为打开时的活动后代。

这些都不是生僻的边界情况,而是屏幕阅读器用户第一分钟就会触发的操作模式。下方的对比将同一个组合框API用两种方式实现——一次使用Mantine的默认值,一次使用React Aria Components——以展示将键盘契约视为规范而非锦上添花时的实际效果。

需要覆盖:Mantine组合框默认状态
<Combobox
store={combobox}
onOptionSubmit={(v) => setValue(v)}
>
<Combobox.Target>
  <InputBase
    // 输入框上没有aria-controls连线
    // Home/End键不在列表框内移动焦点
    // ArrowDown打开但不将焦点放在第1项
    value={value}
    onChange={(e) => setValue(e.currentTarget.value)}
  />
</Combobox.Target>
<Combobox.Dropdown>
  {/* 列表框选项在此渲染 */}
</Combobox.Dropdown>
</Combobox>
原生:React Aria Components组合框默认状态
<ComboBox aria-label="Filter customers">
<Label>Customer</Label>
<Input />
<Popover>
  <ListBox>
    <ListBoxItem>Alpha</ListBoxItem>
    <ListBoxItem>Bravo</ListBoxItem>
    <ListBoxItem>Charlie</ListBoxItem>
  </ListBox>
</Popover>
</ComboBox>
// aria-controls、aria-activedescendant、
// aria-expanded、role=combobox、Home/End、
// PageUp/PageDown、Escape:均默认已连线。
为何这一差距是结构性的,而非偶然的

从已发布规范派生键盘契约的库——React Aria来自WAI-ARIA APG,Ark UI来自Zag.js状态机——将这些契约作为组件支持的唯一行为进行提交。将键盘契约视为功能列表的库,大约实现了其中80%,其余20%留作”未来工作”。而这20%恰恰是辅助技术用户最常按的按键。


5. 无障碍的包体积成本

选择严格库时最常见的反对理由是包体积。审计结果并未支持这一观点。Radix UI原生组件支持按组件进行树摇,每个原生组件的gzip压缩后大小约为7至15 KB;React Aria Components更重——完整包gzip后约95 KB——但同样支持树摇。Headless UI是其中最轻的,整个包gzip后约25 KB。Mantine和Chakra v3均属于功能齐全型,在同一包中附带样式系统,开箱即用的gzip大小约为180至220 KB。

这种权衡是真实存在的,但比讨论所呈现的要小。一个不响应HomeEnd的组合框与一个正确响应的组合框,字节成本大致相同。选择并非”无障碍vs性能”——而是”规范派生行为vs手写行为”,而手写版本往往更大,因为它携带了自己的临时状态机。

7-15 KB
Radix UI每个原生组件(gzip)
25 KB
Headless UI完整包(gzip)
95 KB
React Aria Components完整包(gzip,支持树摇)
约200 KB
Mantine + Chakra v3功能齐全默认值

6. 选型实操手册

1

如果产品是企业级应用且有采购驱动的无障碍要求,选React Aria Components。

它是所有被审计库中唯一API明确派生自WAI-ARIA创作实践指南的库。包比Radix重,但向VPAT审核方说明审计通过情况最为简洁,因为每个原生组件都有已发布的合规声明。

2

如果团队自主维护设计系统,选Radix UI(可选在其上叠加shadcn/ui)。

Radix提供无样式、规范合规的原生组件。shadcn/ui让它们易于复制引入并主题化。需要注意的是shadcn未提供的三个模式——组合框、列表框、菜单栏——应直接导入Radix,而非手写。

3

如果团队以Tailwind为主且只需要有限组件面,选Headless UI——但请审计自己代码中的菜单原生组件。

Headless UI是该领域包体积最小的,提供一个小而经过良好测试的组件面。菜单原生组件的一处缺口已在上文说明;通过在列表框式菜单上显式连线aria-activedescendant,或用项目本地helper进行封装来修复。

4

如果团队重视开箱即用胜过规范合规,选Mantine或Chakra v3——但请规划好覆盖工作。

两款库上手快且开箱即用效果好。但两者都需要针对各组件做额外覆盖,才能通过组合框、开关、滑块(Mantine)或工具提示(Chakra v3)的审计。请将覆盖工作排入引入该库的迭代,而非在审计失败的迭代中亡羊补牢。

5

在引入库之前,对其官方演示运行axe。

各供应商均维护演示站点。将axe DevTools对准它们。如果供应商自己的演示在您计划使用的原生组件上出现违规,这些违规将随之进入您的产品。这一五分钟的检查将您要引入的库与要回避的库区分开来。


结论:规范即契约

能够干净通过axe审计的库,是那些作者将WAI-ARIA创作实践指南视为契约而非参考的库。Radix UI、React Aria Components和Ark UI分别从已发布规范派生其键盘契约和ARIA连线——Radix和React Aria来自APG,Ark UI来自Zag.js状态机——并按规范提交,而非规范的子集。

那些失败的库,并非因为其作者不关心无障碍。它们失败,是因为键盘契约被视为功能列表,而功能列表最终会在80%时停下,而非100%。最后那20%——组合框中的HomeEnd、用Escape关闭悬停打开的工具提示、菜单中第一次ArrowDown时的焦点管理——是用户注意到的部分。

shadcn/ui的情况横跨两个类别。它所提供的组件继承了Radix的规范派生性并通过测试。它不提供的组件是团队手写内部组合框的地方,而那个内部组合框正是下一个axe违规进入代码库的入口。解决方案不是换一个库——而是对那三个模式直接导入Radix,并以和设计系统其他部分同等的认真程度对待它们。

引入库的工程团队应将选型与开发者专区中的其他开发者工具配套使用,在将库发布到生产环境之前对其演示页面运行免费WCAG 2.2扫描,并将结果与完整WCAG 2.2成功标准参考进行基准对比。

“选一个作者将规范视为契约的库,审计就只是走个形式。选一个作者将规范视为参考的库,审计就变成了积压工单。”

— disabilityworld.org工程团队,结尾备注