eslint-plugin-jsx-a11y与html-validate必须协同使用:前者专检jsx动态逻辑(如aria-hidden={ismenuopen ? 'false' : 'true'}),后者覆盖纯html片段(如ssr模板、cms输出),二者互补缺一不可,共同构成全链路无障碍质量门禁。

HTML 代码质量不会靠“重写一遍”自动提升,关键在约束机制和渐进式落地路径。没有统一语义规范、不绑定构建流程、不接入 CI 检查的重构,90% 会退化回老样子。
为什么 eslint-plugin-jsx-a11y 和 html-validate 必须同时用
只用 eslint-plugin-jsx-a11y 覆盖不了纯 HTML 片段(如服务端渲染模板、CMS 输出块、遗留 innerHTML 注入),而只用 html-validate 又抓不到 JSX 层面的动态属性逻辑(比如 aria-hidden={isMenuOpen ? 'false' : 'true'} 写反了)。
实操建议:
- 在 Webpack/Vite 构建中,用
html-validate的 CLI 模式扫描src/**/*.html和public/**/*.html,配置"valid-lang": "error"、"require-skip-link": "warn"等强规则 - 在 ESLint 配置里启用
jsx-a11y/aria-props、jsx-a11y/heading-has-content,并把rulesDirectory指向团队自定义规则(例如禁止div[role="button"]而未绑定onKeyDown) - CI 中两者都设为失败门禁:一个报
aria-required-child错误,一个报duplicate-id,都阻断 PR 合并
如何让 data-* 属性不变成新混乱源
重构常把旧 class 名批量替换成 data-component 或 data-track-id,结果半年后满屏 data-xxx,语义比 class 还难懂。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
实操建议:
- 限定前缀白名单:
data-ui-(仅用于组件边界识别)、data-track-(仅埋点)、data-test-(仅测试定位),其他一律禁止 - 所有
data-ui-*必须在设计系统文档中注册,例如data-ui-tabs-container对应 Tabs 组件根节点,且该值不可由业务层覆盖 - 用 PostHTML 插件在构建时扫描非法
data-,匹配正则/^data-(?!ui|track|test)/并报错
嵌套 <section></section> 和 <article></article> 时,什么情况下必须加 aria-labelledby
当 <section></section> 不含标题元素(<h1>–<h6></h6>
</h1>),或标题是视觉隐藏但未用 aria-label/aria-labelledby 关联时,屏幕阅读器无法建立内容层级,会导致跳过整块区域。
常见错误现象:
- 仪表盘卡片用
<section class="card"></section>包裹,内部只有<div class="card__title">用户统计</div>(无 heading 标签) - 多步骤表单每个
<section></section>用 CSS 隐藏标题文字,仅靠图标示意
实操建议:
- 强制要求:任何无
<h1>–<h6></h6> </h1>的<section></section>或<article></article>,必须有aria-labelledby指向页面内真实存在的 ID,且该 ID 所在元素需有可读文本(不能是空<span aria-hidden="true"></span>) - 用
html-validate规则"require-valid-alt"扩展为"require-section-label"自定义规则,在 CI 中检查 - 设计系统组件库中,
Section组件默认渲染<section aria-labelledby="{id}"></section>,id 由组件自动生成并注入对应<h3 id="{id}"></h3>,业务方不可绕过
真正卡住 HTML 质量跃迁的,从来不是语法对错,而是「谁有权改」和「改错谁负责」——所有校验规则必须绑定到具体角色(设计师提 PR 时触发无障碍扫描,前端提交时触发语义结构检查),否则再好的规则也只是一份 PDF。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










