vscode-html-validate 能检测 aria-* 和 role 的静态误用,如 role="button" 缺 tabindex 或事件;axe-core cli 在运行时检查焦点、对比度等;脚本可自动补 alt 和 button type,但语义判断需人工;html washer 会误删关键语义属性,不可用于生产。

用 vscode-html-validate 检查 aria-* 和 role 的误用
很多“看似可访问”的代码实际违反 WCAG,比如 role="button" 套在 <div> 上却没加 <code>tabindex="0" 或 onclick 事件监听,屏幕阅读器会识别为按钮但无法触发。vscode-html-validate 能捕获这类模式,前提是配置启用 aria-allowed-attr、aria-required-attr 和 aria-valid-attr-value 规则。在 VS Code 的 settings.json 中加入:
"html-validate.options": {
"rules": {
"aria-allowed-attr": "error",
"aria-required-attr": "error",
"aria-valid-attr-value": "error",
"no-inline-style": "warn"
}
}
注意:它不会检查 JS 动态设置的 aria- 属性,只校验静态 HTML;若项目用模板引擎(如 Handlebars),需确保插件能解析后缀为 .hbs 或 .html 的文件。
用 axe-core CLI 在构建前跑可访问性快照
vscode-html-validate 是静态检查,axe-core CLI 才能模拟真实渲染环境,检测焦点顺序、颜色对比度、alt 缺失等运行时问题。执行前需本地起服务(如 npx serve -s dist),再运行:
npx axe-core http://localhost:5000 --tags=wcag2a,wcag2aa --output=accessibility-report.json
常见陷阱:
-
http://localhost:5000必须是完整 URL,不能写./index.html—— axe 需要 HTTP 环境才能加载 JS 和计算样式 - 报告默认只输出失败项,加
--verbose才能看到所有检查项状态 - 若页面依赖登录态,得先手动登录并传入 cookie(
--cookie "session=xxx"),否则大量区域被判定为“不可访问”
批量修复 img 缺失 alt 和 button 缺失 type
人工补 alt 效率低还易漏,可用 Node.js 脚本自动打桩 + 标记待人工审核:
const fs = require('fs');
const html = fs.readFileSync('index.html', 'utf8');
const patched = html
.replace(/@@##@@]*?)\/>/g, (m, attrs) => {
if (!/alt=["']/.test(attrs)) {
return m.replace(/>$/, ` alt="[TODO: describe image]">`);
}
return m;
})
.replace(/<button>]*?)>/g, (m, attrs) => {
if (!/type=["']/.test(attrs)) {
return m.replace(/<button type="button" return m fs.writefilesync patched><p>关键点:</p>
<ul>
<li>正则中用 <code>[^>]*?</code> 避免跨标签匹配,比 <code>.*?</code> 更安全</li>
<li>
<code>alt="[TODO: describe image]"</code> 是显式标记,CI 流程可 grep 出来阻断上线</li>
<li>不自动填空描述,因为语义必须由人判断;同理,不给 <code><a href="#"></a></code> 加 <code>role="button"</code> —— 这属于逻辑重构,脚本不该越界</li>
</ul>
<h3>为什么不能只靠 HTML Washer 或在线工具做可访问性清洗</h3>
<p>HTML Washer 会无差别剥离所有 <code>class</code>、<code>id</code>、<code>aria-</code> 属性,结果可能把 <code>aria-live="polite"</code> 或 <code>id="main-content"</code> 也删了,反而降低可访问性。它适合“克隆布局”场景,不适合生产环境清洗。真正有效的自动化清洗,必须:</p>
<ul>
<li>保留所有语义化属性(<code>alt</code>、<code>lang</code>、<code>required</code>、<code>aria-</code>)</li>
<li>只修正已知反模式(如无 <code>type</code> 的 <code><button></button></code>、无 <code>href</code> 的 <code><a></a></code>)</li>
<li>对不确定项打标而非删除(如空 <code>alt=""</code> 可能合法,但 <code>alt="image"</code> 必须改)</li>
</ul>
<p>最常被忽略的是:可访问性不是“有没有”,而是“用得对不对”。一个 <code>role="navigation"</code> 如果包裹了广告位,比没有更糟糕。</p>
<img></button></button>











