无障碍设计:从首行代码起的科技尊重
|
去年四月,杭州连续下了一周毛毛雨,机房空调坏了三天,冷凝水顺着机柜顶部滴到我键盘左边那排F键上——现在F4按下去还有点粘。那天下午三点十七分,我正用老杨的MacBook Pro切屏看眼动仪数据,他蹲在工位隔断底下拧自己那台Windows笔记本的散热螺丝,螺丝刀拧了七下才松动,手一滑砸在充电线上,屏幕闪了两帧灰。 无障碍设计:从首行代码起的科技尊重。呵,这标题我上周刚在PM晨会PPT第一页看见,字体加粗还配了握手图标。我说“首行代码”?真他妈敢写。我们那套商品详情页组件,初始化render之前先跑了个useAccessibilityHook——结果你猜怎么着?它第一行执行的是document.querySelector(‘#skip-nav’),而这个ID压根儿没人在任何模板里塞过。我原以为是CI漏了,结果查Git历史发现,这个hook是上季度末重构时加的,但skip-nav的DOM结构,是去年双十一前就删掉的。删的人,正是坐在对面喝冰美式的阿哲。他昨天还跟我说:“语义化标签不就是div包span再加个aria-label么?” 桌上有半盒冷掉的黄焖鸡米饭,盖子掀开一半,汤汁浮着层薄油,映得见顶灯倒影。我拿筷子戳了三下才把饭粒扒拉起来。这时候运营总监推门进来,拎着她那个三年前买的安卓机,屏幕裂了两条细缝,像蛛网。她说:“杨工,你们新上的语音跳转,我妈用着卡顿。”老杨没抬头,还在抠散热器滤网里的猫毛——他养了只三花,叫“小满”,上周刚打完疫苗,尾巴尖有点秃。他说:“你妈手机连Chrome 89都不支持,我们默认兼容到91。”总监说:“可竞品能读标题啊。”老杨停下手,指着自己右耳后一块淡褐色痣说:“他们家标题全是div+role=heading,我们是h2。但他们的h2里塞了三个span、一个picture、一个内联SVG、一个用CSS伪元素写的冒号——我们读出来是‘价格¥’空格‘二百七十九’空格‘元’空格‘有货’空格‘立即下单’。谁听得懂?”
文章配图,仅供参考 我原以为这是兼容性问题,结果不是。是我们从头就没让a11y成为约束条件。组件库选型撕逼那次,A组要React Aria,B组坚持Vue Use,最后技术中台拍板:“都接入,但核心动效和焦点管理逻辑复用同一套TS utils。”好嘛,utils里有一千两百行代码,其中三百七十二行在处理tabindex=-1的移除时机——但它压根不判断用户是否启用了屏幕阅读器。判断?没人写。为什么?因为埋点方案里根本没定义“SR session duration”指标。数据说没上报?其实是客户端压根没调useSRDetector()。这个我敢打包票——我们用Proxy劫持了整个navigator.accessibilityFeatures对象,但忘了重写onchange回调。改了之后,发现iOS 15.4以下版本根本不触发这个回调,它只响应get接口。所以——算了,不说了,反正现在生产环境还挂着console.warn(‘SR detection fallback: polling every 300ms’)上个月底做无障碍审计,第三方团队测出47个WCAG 2.1 AA级不达标项。最离谱的是“动态内容更新未播报”这一条——我们的商品库存倒计时,每秒重绘DOM,但aria-live=polite区域根本不在那个div里。它在…在购物车弹窗右上角那个小小的圆点徽章里。那个徽章本身是个svg,用fill属性变色,连text节点都没有。我们把它加了个aria-label="库存变化",结果NVDA读出来是“stock change stock change stock change”,重复三遍,中间没停顿。我截图发给测试同事,她回了个“(点头)”。她昨天刚做完乳腺结节穿刺,左手臂还贴着敷料,拇指一直无意识摩挲绷带边缘。 优胜劣汰。这词儿站得住,但不是按我们想的那样站。不是“做得好就活下来”,是“不踩坑的活下来”。你信不信,只要一个盲人用户连续三次在结算页因focus trap卡住超过十八秒,他的设备就会被风控系统识别为“异常交互流”,自动降权——包括他下次进来的首页曝光优先级。这不是产品写的规则,是广告算法反哺的兜底逻辑。我问过数据平台的人,他说:“哦,那个呀,是实时行为建模里的一个负样本权重项,名字叫blind_interact_punish。”没文档,只有内部SQL里一行注释:“为防止恶意刷单,对低频焦点移动做衰减”。我们管这叫“优胜劣汰”,其实它连淘汰都不算,是直接抹掉你的可见性。 前两天修一个按钮的contrast ratio,Sass变量里写了$color-text-high-contrast:#212121,但设计师给的UI稿用的是#1f1f1f。差俩十六进制数,对比度掉0.7。我把变量改了,PR过完CI,老杨立刻在群里甩来一张图:iPhone SE第二代,暗光模式下,那个按钮跟背景融为一体,像块疤。我没回。因为我知道,就算调成#000,安卓旧机WebView里,font-smoothing还是会让边缘发虚。这种事,改不完。只能挑——挑哪三个地方先保AA,剩下二十一个先挂着warn。这个我说不准。但我知道,下周就要上线618大促主会场,而无障碍review checklist,目前签字栏还空着。 我现在桌上这杯茶凉透了,茶叶沉到底,像一小片褐色的岛。窗外雨还没停。我准备把a11y-linter插件从pre-commit钩子里撤掉——它太吵,每次commit都要报127个warning,其中有八十三个是“img缺少alt”,但我们图床返回的CDN地址里,路径里就含关键词,比如//img.xxx.com/whitebg_100x100.png,团队早约定“用文件名语义替代alt文本”。没人质疑过。就像没人质疑过,为什么所有toast提示都设了role=alert,但偏偏结算成功页那个弹窗,用了role=status……因为当年第一个提PR的人,误删了那一行role属性,后续十六次迭代,没人发现。我也懒得改了。先保首屏。别的,等618过了再说。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

