htmlhint锚定可访问性底线需聚焦5条硬性规则:doctype-first、doctype-html5、html-lang-require、id-unique、alt-require,写入.htmlhintrc并配置vs code保存时校验;alt-require要求装饰图用alt=""、功能图标带意图、图表描述趋势;html-lang-require须指定具体值如lang="zh-cn";语义标签替换需匹配内容与role,多须加aria-label区分;标题层级须严格递进且全页仅一个;aria仅在原生标签能力不足时精准使用,避免滥用破坏可访问性。

平滑升级不是“一次性替换所有 <div>”,而是让每次提交都比上一次更可访问——关键在于锚定 5 条硬性规则、分层验证、拒绝语义漂移。
<h3>怎么用 HTMLHint 锚定可访问性底线</h3>
<p>别一上来就启用全部 40+ 规则。真正能阻断结构性退化的只有 5 条:<code>doctype-first、doctype-html5、html-lang-require、id-unique、alt-require。它们直接对应怪异模式、语音引擎失效、document.getElementById() 行为错乱、屏幕阅读器丢信息等真实故障。
- 把这 5 条写进项目根目录的
.htmlhintrc,VS Code 保存时立刻报错,比 Code Review 提前发现缺陷 -
alt-require不是“加个空字符串就行”:装饰图用alt="",功能图标必须带意图(如alt="搜索"),图表需描述数据趋势而非只写“图表” -
html-lang-require必须配具体值,不能只写lang="zh",否则部分读屏无法切换方言引擎
为什么 <nav></nav> 换了但可访问性没提升
把 <div class="nav"> 改成 <code><nav></nav> 只是第一步。如果里面没有实际链接、或全是 <span></span> + JS click,辅助技术仍会忽略它——<nav></nav> 的隐含 role 是 navigation,但内容不匹配,role 就形同虚设。
- 检查 DOM:用 Chrome DevTools 的 Accessibility 面板看 computed role 是否为
navigation,name 是否为空 - 多个
<nav></nav>必须加aria-label区分,比如<nav aria-label="主导航"></nav>和<nav aria-label="页脚导航"></nav> - 纯视觉分隔的区块(如广告位)别硬套
<section></section>,它默认有regionrole,会干扰屏幕阅读器大纲生成
标题层级断裂比没用语义标签更致命
很多页面从 <h2></h2> 开始,或在 <main></main> 外堆了三个 <h1></h1>。这对键盘用户和读屏用户是灾难:大纲树完全错乱,无法跳转到“主内容”或“产品介绍”板块。
- 全页只允许一个
<h1></h1>,代表页面核心主题(通常是 logo 或主标题) -
<main></main>内部标题必须严格递进:<h2></h2>→<h3></h3>→<h4></h4>,禁止跳级或降级 - CSS 隐藏
<h1></h1>时,必须同步加aria-hidden="true",否则读屏会播报两次(视觉隐藏 + 语音播报)
什么时候该用 ARIA,什么时候不该用
ARIA 不是语义化补丁,而是当原生标签能力不足时的精准干预。滥用反而破坏可访问性——比如给已有 <label for="email"></label> 的输入框再加 aria-labelledby,会导致重复播报。
- 模态框必须同时设置:
role="dialog"、aria-labelledby(指向标题 ID)、aria-modal="true" - 图标按钮(如 ✕ 关闭)必须用
aria-label,title属性对读屏无效 - 动态加载的内容(如搜索建议列表)需用
aria-live="polite",但仅限真正需要通知用户的变更
最易被忽略的点:可访问性不是“加完标签就结束”,而是每次 DOM 变更后,都要验证角色、名称、状态是否与用户预期一致——尤其在 JS 控制的交互区域,原生语义常被覆盖,必须手动补救。











