@william-xu-web/c-a11y
网页无障碍辅助插件
A11y 是一个轻量、独立、可无缝集成到任何网页的无障碍工具栏。它通过浮动按钮提供 20 余项辅助功能,覆盖视觉、运动、认知与听觉障碍,帮助您快速提升网站的可访问性,并满足 WCAG 2.1 合规要求。
快速开始
方式一:NPM
yarn add @william-xu-web/c-a11y
import { init } from "@william-xu-web/c-a11y";
const widget = init({
lang: "zh",
position: "bottom-right",
});
// 需要时销毁插件并清理所有事件监听
widget.destroy();
方式二:Script 标签
在 HTML 中引入脚本,脚本从 node_modules 目录下的 c-a11y.min.js 文件引入,插件即自动初始化,无需额外 JavaScript 代码:
<script src="/path/to/c-a11y.min.js" defer></script>
功能全景
所有功能均按需启用,用户可随时开关,偏好设置自动保存至本地。
视觉与显示辅助
| 功能 | WCAG 参考 | 适用人群 |
|---|---|---|
| 字体缩放(放大/缩小/重置) | 1.4.4 | 低视力、老年人 |
| 高对比度模式(深色/浅色/反色) | 1.4.3 | 低视力 |
| 深色模式 | 1.4.3 | 光敏感人群 |
| 灰度显示 | 1.4.1 | 色盲 |
| 色彩饱和度滑块 | 1.4.1 | 色彩敏感者 |
| 文字间距调整 | 1.4.12 | 阅读障碍、低视力 |
| 阅读障碍专用字体(OpenDyslexic) | 最佳实践 | 阅读障碍 |
| 隐藏图片 | 最佳实践 | 认知障碍 |
| 色盲模拟滤镜 | 1.4.1 | 开发者测试、无障碍意识教育 |
导航与阅读辅助
| 功能 | WCAG 参考 | 适用人群 |
|---|---|---|
| 全键盘导航支持 | 2.1.1 | 运动障碍 |
| 焦点指示器增强 | 2.4.7 | 运动障碍、低视力 |
| 标题地图 / 页面目录 | 2.4.10 | 屏幕阅读器用户 |
| ARIA 地标结构展示 | 2.4.1 | 屏幕阅读器用户 |
| 阅读辅助标尺(遮光引导线) | 最佳实践 | 阅读障碍、多动症 |
| 行聚焦 / 内容遮罩 | 最佳实践 | 多动症、认知障碍 |
| 大光标模式 | 最佳实践 | 运动障碍、低视力 |
| 屏幕阅读器预览 | 1.1.1, 1.3.1 | 开发者、测试人员 |
媒体与内容辅助
| 功能 | WCAG 参考 | 适用人群 |
|---|---|---|
| 悬停朗读(TTS) | 最佳实践 | 视障、低视力 |
| 选中朗读(TTS) | 最佳实践 | 视障、低视力 |
| 整页朗读(TTS) | 最佳实践 | 视障、低视力 |
| 链接高亮显示 | 1.4.1, 2.4.4 | 低视力、认知障碍 |
| 图片替代文本覆盖显示 | 1.1.1 | 视障、低视力 |
| 停止所有动画 | 2.3.1, 2.3.3 | 癫痫、前庭障碍 |
| 静音所有声音 | 1.4.2 | 听障、认知障碍 |
配置参数
您可以通过全局对象 window.OpenA11yConfig 在脚本加载前进行配置。
<script>
window.OpenA11yConfig = {
position: "bottom-right", // 按钮位置
lang: "zh", // 界面语言
bottomOffset: 20, // 桌面端向上偏移(px)
mobileBottomOffset: 60, // 移动端向上偏移(px)
statementUrl: "/accessibility-statement", // 外部无障碍声明链接
statementData: {
// 内置声明生成器数据
orgName: "我的公司",
orgPhone: "13088888888",
orgEmail: "access@example.com",
coordinatorName: "张三",
lastAuditDate: "2026-01-15",
},
};
</script>
<script src="/path/to/c-a11y.min.js" defer></script>
配置项说明
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
position |
string |
'bottom-left' |
可选:bottom-left、bottom-right、top-left、top-right |
lang |
string |
自动检测 | 界面语言:'zh' 或 'en' |
bottomOffset |
number |
0 |
桌面端(屏幕 > 768px)按钮额外向上偏移,仅对底部位置生效 |
mobileBottomOffset |
number |
0 |
移动端(屏幕 ≤ 768px)额外向上偏移,适用于底部固定导航栏的页面 |
statementUrl |
string |
— | 若您已有无障碍声明页面,可在此填写完整 URL |
statementData |
object |
— | 若需内置声明生成器,提供机构信息即可自动生成声明 |
多语言支持
插件界面内置 中文(zh) 和 英语(en) 两种语言,用户可随时在工具栏中切换。
合规性说明
本插件不仅覆盖 WCAG 2.1 的常用标准,还额外支持以下成功准则:
- 1.4.10 回流(Reflow)
- 1.4.12 文字间距(Text Spacing)
- 1.4.13 悬停或焦点时的内容(Content on Hover or Focus)
- 2.3.3 交互动画(Animation from Interactions)
- 4.1.3 状态消息(Status Messages)
项目架构
目录结构
src/
c-a11y.js # 主入口
styles.js # 所有 CSS(注入 Shadow DOM)
i18n.js # 中/英翻译
storage.js # localStorage 持久化
utils.js # 共用工具函数
modules/ # 每个功能独立模块(共 24 个)
dist/
c-a11y.min.js # 压缩版 IIFE(约 89 KB)
c-a11y.esm.js # ES Module 版本(供打包工具使用)
demo.html # 功能演示页面
设计特点
- Shadow DOM — 样式隔离,完全避免与宿主页面 CSS 冲突。
- 零依赖 — 纯原生 JavaScript,无需加载任何第三方库。
- 模块化 — 每个功能提供
enable()/disable()/toggle()方法,便于扩展。 - 状态持久化 — 用户偏好自动保存至
localStorage,跨会话保留。 - ARIA 实时区域 — 为屏幕阅读器提供状态通知(WCAG 4.1.3)。
常见问题
悬停朗读/选中朗读无法正确朗读中文
问题描述
当页面 HTML 设置了 <html lang="en"> 时,即使插件界面切换到中文,悬停朗读和选中朗读功能仍会使用英文语音朗读中文内容,导致发音异常或无法理解。
原因分析
TTS(文本转语音)模块的语言检测逻辑优先使用页面 HTML 的 lang 属性:
_getLang() {
const pageLang = document.documentElement.lang; // 优先读取 <html lang="...">
const raw = pageLang || getLanguage() || 'en'; // 其次才是插件界面语言
return LANG_MAP[raw] || raw;
}
这样设计是为了让 TTS 遵循页面的内容语言,而非插件的界面语言。例如,一个英文网站(<html lang="en">)上使用中文界面的用户,朗读时仍应使用英文语音。
解决方案
- 推荐做法:在页面 HTML 中正确设置语言属性
<!-- 中文网站 -->
<html lang="zh">
<!-- 或更精确 -->
<html lang="zh-CN"></html>
</html>
- 临时方案:如果页面语言与内容语言不一致,可以在控制台临时修改:
document.documentElement.lang = "zh-CN";
- 检查系统语音:确保操作系统已安装中文语音包
// 在浏览器控制台运行,查看是否有中文语音
speechSynthesis.getVoices().filter((v) => v.lang.includes("zh"));
- macOS:自带中文语音(Ting-Ting)
- Windows:需在"设置 → 时间和语言 → 语言"中添加中文语言包
- Linux:通常需要额外安装 espeak 或 festival 等语音合成引擎
Webpack3 引入 ES Module 依赖包编译报 Unexpected token 语法错误
问题描述
项目基于 Webpack3 构建,引入 @william-xu-web/c-a11y 依赖后启动编译报错,出现 Unexpected token 错误,根源为该依赖打包产物为 ES Module 格式(含 import/export 语法),Webpack3 编译时无法识别解析 ESM 语法,构建流程直接中断。
原因分析
- Webpack3 仅原生支持 CommonJS 模块化语法,不兼容 ES Module (import/export) 语法,无内置 ESM 解析能力。
- 目标依赖
@william-xu-web/c-a11y/dist/c-a11y.esm.js采用 ESM 规范打包,存在 Webpack3 无法识别的模块化语法。 - Webpack3 无
type: "javascript/auto"兼容配置,无法使用高版本 Webpack 适配 ESM 的配置写法。 - 项目默认 babel-loader 全局排除所有 node_modules 文件,未对该特殊依赖单独放行转译,导致 ESM 语法未被编译转换。
解决方案
1. 调整 babel-loader 排除规则(核心操作)
修改 Webpack3 构建配置,无需降级依赖包版本,适配性最强。
找到项目 webpack.base.conf.js 中的 babel-loader 配置,修改排除规则,放行报错依赖包参与 babel 转译:
// 原配置
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
// 修改后最终配置
{
test: /\.js$/,
loader: 'babel-loader',
exclude: file => {
// 仅放行 @william-xu-web-c-a11y 依赖,其余 node_modules 正常排除
if (file.includes('@william-xu-web/c-a11y')) return false
return /node_modules/.test(file)
}
}
2. 配置 Babel 强制转换模块化规范
在项目根目录 .babelrc 中添加配置,强制将 ESM 转为 Webpack3 识别的 CommonJS:
{
"presets": [
[
"env",
{
"modules": "commonjs"
}
]
]
}
补充注意事项
- Webpack3 禁止使用
rule.type相关配置,该配置仅 Webpack4 及以上版本支持。 - Vue-cli2 等基于 Webpack3 搭建的老旧 Vue 项目,统一修改
build/webpack.base.conf.js配置即可。
浏览器支持
| 浏览器 | 最低版本 |
|---|---|
| Chrome | 80+ |
| Firefox | 78+ |
| Safari | 14+ |
| Edge | 80+ |