语义标签不可替换为div类名,必须用<header><nav><main>等;内联事件需迁移到data-js钩子+addEventListener;空标签和注释清理前须验证可访问性影响;删脚本前须确认无障碍事件监听器是否依赖。

删掉无语义的前先确认是否影响屏幕阅读器浏览器和辅助技术不读 class 名,只认 <header>、<nav>、<main> 这类语义标签。把 <div class="header"> 当页眉用,等于主动屏蔽了语义信息——NVDA 或 VoiceOver 会跳过它,SEO 权重也归零。检查时别只看视觉,得打开 Chrome 的“Accessibility”面板(Elements → 右键元素 → “Inspect Accessibility”),看 role 是否为 banner;如果不是,说明没被识别为页眉。
替换原则很直接:<div class="header"> → <header>,<div class="nav"> → <nav>,但注意:<main> 全局只能有一个,且不能嵌套在 <section> 里,否则部分读屏器直接忽略。
清理内联事件处理器时必须保留 Event 对象访问能力
onclick="doSomething('id-123')" 看似省事,实则断掉了 e.preventDefault()、e.target 和模块化封装能力。函数必须挂全局,传参靠字符串拼接,一改就报 ReferenceError: doSomething is not defined。
迁移要分两步走:
立即学习“前端免费学习笔记(深入)”;
- 加
data-js 钩子替代 class:把 <button onclick="submitForm()"> 改成 <button data-js="form-submit">
- 统一用
addEventListener 绑定:在 DOMContentLoaded 后执行 document.querySelectorAll('[data-js="form-submit"]').forEach(el => el.addEventListener('click', handleSubmit))
- 如果原逻辑依赖动态参数(如 ID),改用
el.dataset.id 读取,而不是拼字符串
删空标签或注释前先验证是否干扰首屏可访问性
空标签如 <div></div>、<p></p> 不影响渲染,但可能被 JS 动态注入内容,或被 CSS 的 :empty 伪类控制样式;更隐蔽的是注释——<!-- old skip-link --> 虽不显示,却占字节流位置,尤其在 <head> 里,可能把关键 <meta charset> 推出首 1024 字节,导致 Safari 解析乱码。
安全清理方式:
- 用
perl -0777 -i -pe 's/<!--.*?-->//gs' index.html 批量删跨行注释(sed 处理不了多行)
- 空标签不能全删:先执行
document.querySelectorAll('div:empty, p:empty').forEach(el => console.log(el.parentElement?.className)),确认父容器没依赖它占位
- 删完立刻用 Lighthouse 跑一次“Accessibility”审计,重点看“Heading levels”和“Link purpose”是否异常
删脚本前检查是否注册了无障碍相关事件监听器
很多老项目用内联脚本或全局函数处理键盘导航、焦点管理、ARIA 属性切换——比如 tabindex 动态增删、aria-expanded 切换、focus() 模拟跳转。直接删掉 <script src="a11y-helpers.js"></script>,下拉菜单可能无法用键盘展开,搜索框失去自动聚焦。
排查必须手动做:
- 在 Console 执行
getEventListeners(document) 和 getEventListeners(window),看是否有 keydown、focusin、click 监听器绑定在全局作用域
- 全局搜
aria-、tabindex、focus(、scrollIntoView,确认调用来源是否还在
- 用键盘 Tab 键逐个测试交互控件:能否进、能否出、是否卡死、焦点顺序是否合理
真正难清理的不是代码本身,而是那些没文档、没测试、靠“试出来”的键盘操作链——它们藏在没人敢动的 JS 文件里,删错一行,残障用户就卡在登录页。
浏览器和辅助技术不读 class 名,只认 <header>、<nav>、<main> 这类语义标签。把 <div class="header"> 当页眉用,等于主动屏蔽了语义信息——NVDA 或 VoiceOver 会跳过它,SEO 权重也归零。检查时别只看视觉,得打开 Chrome 的“Accessibility”面板(Elements → 右键元素 → “Inspect Accessibility”),看 role 是否为 banner;如果不是,说明没被识别为页眉。
替换原则很直接:<div class="header"> → <header>,<div class="nav"> → <nav>,但注意:<main> 全局只能有一个,且不能嵌套在 <section> 里,否则部分读屏器直接忽略。
清理内联事件处理器时必须保留 Event 对象访问能力
onclick="doSomething('id-123')" 看似省事,实则断掉了 e.preventDefault()、e.target 和模块化封装能力。函数必须挂全局,传参靠字符串拼接,一改就报 ReferenceError: doSomething is not defined。
迁移要分两步走:
立即学习“前端免费学习笔记(深入)”;
- 加
data-js钩子替代 class:把<button onclick="submitForm()">改成<button data-js="form-submit"> - 统一用
addEventListener绑定:在 DOMContentLoaded 后执行document.querySelectorAll('[data-js="form-submit"]').forEach(el => el.addEventListener('click', handleSubmit)) - 如果原逻辑依赖动态参数(如 ID),改用
el.dataset.id读取,而不是拼字符串
删空标签或注释前先验证是否干扰首屏可访问性
空标签如 <div></div>、<p></p> 不影响渲染,但可能被 JS 动态注入内容,或被 CSS 的 :empty 伪类控制样式;更隐蔽的是注释——<!-- old skip-link --> 虽不显示,却占字节流位置,尤其在 <head> 里,可能把关键 <meta charset> 推出首 1024 字节,导致 Safari 解析乱码。
安全清理方式:
- 用
perl -0777 -i -pe 's/<!--.*?-->//gs' index.html批量删跨行注释(sed处理不了多行) - 空标签不能全删:先执行
document.querySelectorAll('div:empty, p:empty').forEach(el => console.log(el.parentElement?.className)),确认父容器没依赖它占位 - 删完立刻用 Lighthouse 跑一次“Accessibility”审计,重点看“Heading levels”和“Link purpose”是否异常
删脚本前检查是否注册了无障碍相关事件监听器
很多老项目用内联脚本或全局函数处理键盘导航、焦点管理、ARIA 属性切换——比如 tabindex 动态增删、aria-expanded 切换、focus() 模拟跳转。直接删掉 <script src="a11y-helpers.js"></script>,下拉菜单可能无法用键盘展开,搜索框失去自动聚焦。
排查必须手动做:
- 在 Console 执行
getEventListeners(document)和getEventListeners(window),看是否有keydown、focusin、click监听器绑定在全局作用域 - 全局搜
aria-、tabindex、focus(、scrollIntoView,确认调用来源是否还在 - 用键盘 Tab 键逐个测试交互控件:能否进、能否出、是否卡死、焦点顺序是否合理
真正难清理的不是代码本身,而是那些没文档、没测试、靠“试出来”的键盘操作链——它们藏在没人敢动的 JS 文件里,删错一行,残障用户就卡在登录页。



















