加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0l.com.cn/)- 应用程序、AI行业应用、CDN、低代码、区块链!
当前位置: 首页 > 创业 > 创业经验 > 正文

技术筑基,内容为本:无障碍设计的双轮驱动

发布时间:2026-11-06 11:08:14 所属栏目:创业经验 来源:DaWei
导读:文章配图,仅供参考  上个季度,我蹲在客户那个破站的前端代码里翻了十八秒,就为确认一个 aria-live 区域有没有被 Vue 的 key 机制干掉——结果发现根本没配 aria-live,连 region 都没设,全靠 JS 手动 .innerHTML 插文本

文章配图,仅供参考

  上个季度,我蹲在客户那个破站的前端代码里翻了十八秒,就为确认一个 aria-live 区域有没有被 Vue 的 key 机制干掉——结果发现根本没配 aria-live,连 region 都没设,全靠 JS 手动 .innerHTML 插文本然后 setTimeout 喊 screen reader。我原以为是开发偷懒,结果溯源到构建脚本里,看见一行注释:// 屏幕朗读器测试用例暂不覆盖,待安全基线对齐后补充。我盯着这行字看了半分钟,手悬在键盘上没敲回车。


  冷眼看着这个“双轮驱动”被贴在晨会 PPT 第三页,左轮写“技术筑基”,右轮写“内容为本”。可昨晚三点十二分,群里突然 @全员,发了个截图:WAF 日志里连续十七条 /accessibility/announce?msg=xxx 的 GET 请求,来源 IP 是 103.158.212.97——这串地址我熟,上个月红队打穿测试环境时用的跳板之一,但这次他们根本没走漏洞,就冲着语音播报 API 去的。不是爆破,不是注入,就反复塞“您的订单已取消,请检查邮箱”,语气平静得像客服机器人。我删掉刚打的一句“建议加 Referer 校验”,改打:“先查下这个接口有没有日志脱敏,别把用户手机号拼进 msg 参数里。”


  服务器上多出来一个文件,叫 /var/www/html/static/a11y/_test_announce_stub.js,时间戳是上周四 02:17,md5 和 git commit 记录对不上。老张说他没推,小李说他只改了 CSS,运维那边 logaudit 查了三遍,说是 Jenkins job 跑挂后残留的临时产物。我没信。但也没深挖,因为第二天客户 QA 直接拎着笔记本冲进会议室,说“视障用户反馈付款成功页不读‘支付完成’,只读‘按钮’两个字”,而我们刚在测试报告里打了✅——那报告是我自己签的字。这个我敢打包票,签字前我还念了一遍那句“支付已完成”,语音助手也念了,听起来没问题。可问题是,那个用户用的是 NVDA 2023.4 + Chrome 124,不是我测的 Edge 126。这个我说不准。


  安全是成本不是收入。这句话我背了七年,现在它卡在我喉咙里,比上次误配 CSP 导致所有内联 script 被 block 还难受。你见过谁给无障碍做渗透测试?我试过。拿 axe-core 扫出一堆 contrast ratio 不达标,导出 CSV 改成 Burp 的 intruder payload,跑了一夜,撞出来两个能触发 XSS 的富文本渲染点——但那俩点早在去年五月就被 WAF 规则封死了,规则名还叫 a11y_xss_2023_q2。可没人告诉我,为什么封的是渲染层,而不是输入层;为什么封了 xss,却放过了 aria-expanded 值直接从 URL query 注入,然后被 VoiceOver 当作状态变更播报三次。我问架构师,他调出一张图,指着“语义层校验模块”说:“这块由内容团队负责,我们只提供基础组件。” 我点点头,关掉 tab,顺手清空了浏览器历史记录里的 /admin/a11y/debug。


  前天晚上抓包抓到一半,线索断了。不是丢包,是响应头里 Content-Encoding: br,但我机器上 brotli 解码一直 fail,最后发现是中间 CDN 把 Transfer-Encoding 改成了 chunked,又把 body 末尾切掉了十七个字节。那个字节正好卡在 aria-label 的闭合引号前面。所以屏幕阅读器报错,卡在“请输”就停住,后面“入手机号”四个字永远没说出来。我重放了二十三次,直到凌晨一点零八分,发现 Firefox DevTools 的 Accessibility 面板里有个“force refresh tree”的隐藏按钮——点完它,页面重新朗读,完整了。但我没截图,也没留 log。因为那一刻我突然想起,上个月渗透测试报告里有一行小字:“部分无障碍状态依赖 client-side DOM 重建时机,非原子操作,不可控。” 这句话当时我没划重点。


  王工昨天拿台老款 iPhone 12 来试,说 VoiceOver 一碰那个提交按钮就卡顿三秒,然后自动跳到页首。我让他录屏,视频里时间显示 04:36:22,背景音是空调外机嗡嗡响。我放大看他手指悬停位置,发现他指甲有点裂——不是重点,但那天我正好也剪过指甲,左手食指也是第三道横纹那里开了个小口子。他退出 App 重进,卡顿没了。再退,又有了。我没让他重装系统,只把 button 上的 role="button" 删了,换成原生 button。他嗯了一声,说“这下顺了”,起身去茶水间泡枸杞。回来时保温杯盖子没拧紧,滴了两滴在键盘上,其中一滴刚好落在 Delete 键旁边。


  我原以为搞清 ARIA 规范、吃透 WCAG 2.2、把所有 color contrast 算到小数点后三位,就能守住底线。结果上个月上线后第七天,视障用户群有人发语音消息,三十秒,语速慢,说“你们那个修改密码页,第三步验证问题选完之后,焦点消失了,我不知道下一步在哪”。我听三遍才听懂,因为录音里混进了地铁报站声:“下一站,北苑路北……” 我立刻去看那段代码,发现我们用了 tabindex="-1" 动态聚焦,但 Safari + VoiceOver 组合里,-1 会被忽略。这个我知道。但我在测试清单里写的却是“验证 Safari 浏览器是否支持动态聚焦”,没写“是否在 VoiceOver 模式下触发”。清单是我自己填的。


  现在我把 accessibility check 嵌进 CI,跑在每轮 PR 后。它能抓出 contrast 不足、aria-required-children 缺失、landmark 重复——但它抓不出“读到‘请输入新密码’时,用户其实正听着导航软件说‘前方二百米右转’”。这没法测。我也不打算加用例。下周五我要去现场,带三台真机,一台装 NVDA,一台装 JAWS,一台我自己用。别的不带,就带个降噪耳机。要不要同步录屏?我不确定。反正服务器上的 _test_announce_stub.js 还在那儿,没人删,也没人动。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!