扫清障碍,当个自私的利他者

最近刷到 Prot 对视障用户采访 Prot Asks: Arkadiusz about blindness, Emacspeak, Hyperbole, Chinese and Slavi... , 有点受到触动,想起换了博客框架后还没对无障碍投入精力过。拿 Talkback 测试时越测越觉得羞 愧,还是有挺多问题的!优化掉后写篇博文记录下吧。

Why

近些年工作要盯着屏幕(加上糟糕用眼习惯)导致近视度数持续加深,下班走出大厦望着远处越发模糊的招牌,我开始有 点担心到了最后我会不会视网膜脱落?或者路过某熊孩子扔鞭炮到井里导致沼气爆炸绷飞的石子正中我的眼球?又或者某天夜晚一个对应 眼球组织的免疫细胞从淋巴逃逸然后导致免疫风暴让我眼球被免疫系统攻击?即便失去视力,我也不会停止「玩」电子设备,未 雨绸缪为了可能要依赖 Talkback 的自己,开始加强下这个站点的无障碍建设,或许「顺带」方便了需要这些的人 1

没有任何依据,但我认为利他行为总在满足了自身才会真切出现,从小在「让梨」教导中被迫给梨的小孩和在自己吃了一个梨不需要的情况下让梨收 获到感谢为之快乐的小孩,在成年时哪个会更自发做出「让梨」行为?

优化

视障人士「装」明眼人很困难,明眼人「装」视障人士却又很简单,闭上双眼就能可以了,只是有眼睛的人都不会「放弃」使用 自己双眼的。那就克服睁眼的冲动,在安卓手机同时按下上下音量键几秒钟就能开启 TalkBack 将自己当成视障人士。在 TalkBack 模 式下,平常的单击是双击,左右滑动就相当于 PC 的 TAB 键切换元素的焦点。很好,那么就在这下面看看我这个博客站点怎么样吧。

导航栏

首先是因为导航栏的存在,使用切换焦点模式「听览」网页的话会要过一遍导航栏的所有元素,在打开了几个网页后就有点烦躁了。在搜索 时看到了 {Draft} Skip Link - Easy Checks | Web Accessibility Initiative (WAI) | W3C 方案,在网页的第一个焦点放 置指向网页主题的内容主体 id 的链接就好了。

大概例子(这里用 SXML 表示 HTML ,因为我现在还没做 HTML 语法高亮,如果不知道 SXML 是什 么可以看我之前相关文章 Hello Haunt, 又一次换了博客框架):

(nav (@ (class "nav"))
    (a (@ (class "skip-link") (href "#main-content")) "跳到主要内容")
    (a (@ (href "/")
          (class "brand"))
       (span "狐狸反走矣"))
    ...)

然后定义主要内容:

(main (@ (id "main-content") (tabindex "-1"))
      (h1 "主页")
      ...)

注意 main 标签默认是不可聚焦的,所以要附上 tabindex="-1" 属性强制将焦点聚焦上去,否 则会出现聚焦到 main 然后失焦又返回到网页开头产生「如跳」的现象。如果要将这个链接做只对焦点模式下才 显示(对正常浏览用户隐藏)的话可以加上这样的 css :

.skip-link {
    position: absolute;
    top: -100px;
    left: 0;
    background: #000;
    color: #fff;
    padding: 10px 20px;
    z-index: 10001;
}

.skip-link:focus {
    top: 0;
}

标题元素

网页尽量出现唯一的 H1 元素,这样 TalkBack 会在网页加载完后自动将标题念出来。然后是标题元素尽量 以 H1 H2 H3 顺序排起,不要跳顺序如 H1 H3 ,这样让 TalkBack 在标题模式下的导航不会出语义问题。

(在现在这篇文章发布时我还没把侧边栏整好,现在还在用着 H4 ,之后得优化下)

脚本焦点操作

碰上了个诡异现象,在选择了非「普通」主题后,打开网页后焦点会跳在主题选单上,排查一番后发现是根 据 localStorage 值更新主题菜单当前值的 js(lips) 代码:

(option.setAttribute "selected" #t)

会导致焦点跳转,想了个快速变通方法是将选择菜单组件用 aria-hidden 属性暂时覆盖掉:

(define options select.options)
(select.setAttribute "aria-hidden" "true")
...
  (option.setAttribute "selected" #t)
...
(select.removeAttribute "aria-hidden")

这样操作组件时就不会导致焦点跳转了,写到这确实有点感到感概,这两三个月里,配置选单也是实在干扰到了使用读屏软件 的访客……

蒙上双眼,它是什么?

在闭上眼睛用着 TalkBack 的时候,经常会出现听起来莫名奇妙的反馈……「1」「2」、「左箭头」、「链接」。对照 看了下发现是些明眼人看了一目了然的元素在读屏的时候会觉得很奇怪。

「1」、「2」这些其实是脚注,那么这里使用 aria-label 加上描述:

`(sup (a (@ ,@attrs (aria-label ,(string-append "脚注" id))) ,@children))

这样读屏软件就会念出「脚注1」、「脚注2」了。

「左箭头」、「右箭头」是什么?原来是关于 WebRing 的相关导航,写成这样:

(nav (@ (aria-label "Fediring"))
              (a (@ (href "https://fediring.net/previous?host=blog.southfox.me")
                    (aria-label "上一个 Fediring 站点"))
                 "←")
              (a (@ (href "https://fediring.net"))
                 "Fediring")
              (a (@ (href "https://fediring.net/next?host=blog.southfox.me")
                    (aria-label "下一个 Fediring 站点"))
                 "→"))

那么读屏软件就不会念出「左箭头」、「右箭头」而是念出「上一个 Fediring 站点」、「下一个 Fediring 站点」了。

图片替代文本

之前,我其实也不怎么写图片替代文本的,但在 22 年看到我采访了几位盲人程序员,看看他们是怎么写代码的【差评君】_哔哩哔哩_bilibili 这个视频后,受到触动开始尽量写下图片替代文本了。在写了一段时间后发现这倒是方便我用 Elasticsearch 搜索相关图片,很多次我想找 自己 Mastodon 站点上的贴文都是靠搜替代文本找到的。所以就算在这里,这个博客中我也会尽量写下图片替代文本,因为确实方便我 用 ripgrep 搜索了。

另外是视障也是分等级和先天还是后天,在写相关替代文本时加上颜色光泽描述也是可行的(也不知道为何有视障就是完全看不清的迷思流行呢……?)。

地标模式

HTML5 发展到现在已经有专门语义标签例如 main, nav, header, footer 了,用上这些 TalkBack 在启用了「地标」模式 时可以很方便快速跳转到这些标签上。

不要细细地切成臊子

现在懒得写行内代码了,没成想这在无障碍下也有好处,因为 TalkBack 在碰到 <code> <a> 标签会中断当前段落朗读然后等待 用户跳转下个焦点,然后朗读完 <code> <a> 标签后又会暂停等待用户跳转下个焦点(所以为什么要这么设计呢)。就是说行内代 码相当于将段落朗读斩成了三份,试了下之前有在勤写行内代码的文章,真得很折磨,要自己不停滑动下一个焦点。对于这种情 况,发现在 TalkBack 这边划一个倒 L 打开菜单选择「从当前焦点朗读」直接一口气读完文章才是解脱……

最后

因为好奇去翻看 tvraman/emacspeak 2 代码感到有点 肃然了,里面一个一个 emacspeak-magit.el, emacspeak-bookmark.el, emacspeak-calc.el, emacspeak-dbug.el, emacspeak-dired.el, emacspeak-ediff.el, emacspeak-evil.el, emacspeak-google.el, emacspeak-vterm.el 等 百来个文件,明眼人的习以为常对于视障人士来说是要尽力「争取」的事啊。有点后悔没在一开始就考虑无障碍,不过栽树最好的时间是三十年前 或者……现在。

脚注

1 中国残疾人联合会-3-2 全国残疾人人口基础库主要数据 :已办理残疾症 人数 38250009 、视力残疾人数 3945609 、肢体残疾人数 19819889 ,哪怕不算潜在没办证的残疾人这都已经不是小数目了。

2 Emacspeak --The Complete Audio Desktop 官网上还有可爱狗狗。

如不想授权 Giscus 应用,也可以点击下方左上角数字直接跳转到 Github Discussions 进行评论。