设计页面时,为了提升用户点击体验,会有扩大元素的可点击区域的需求——即我们看见的元素很小,但实际可响应的区域却是大的。比如,用一个 <a> 标签包裹一大块内容,以达到点击这块区域的任何部分都会跳转,这就是我们所谓的“块链接”。功能上当然没问题,但却没有考虑屏幕阅读器使用者的体验。
《Block Links, Cards, Clickable Regions, Etc.》一文的作者 Adrian Roselli 对此话题做了讨论并给出了解决方案。简单地说,就是不要使用 <a> 或 <button> 去包含大量内容,而是使用下面这种方式来达到扩大响应区域的效果。
a::after,
button::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
不仅能达到效果,而且对屏幕阅读也是友好的。
如果你对细节感兴趣,可以继续阅读下面我翻译的正文部分~~
链接
使用 <a href> 包裹所有内容实现的块链接(block link)的做法是可能最不可取的。
例如,下面的代码:
<article>
<a href="https://example.com/linkwrap" rel="nofollow">
<h3>Wrapping Entire Thing</h3>
<img src="https://www.fillmurray.com/640/360" alt="Bill Murray on the award carpet.">
<p>
Gastropub sartorial ... affogato bicycle rights.
</p>
</a>
</article>
<style>
a:link {
text-decoration: none;
}
</style>
如果这里的 <a> 标签,没有设置 display: block ,就会有问题。
可以看见,在鼠标划入的过程中,并不总是悬停 (以出现下划线为标志)在链接上的。在文本周围、图片与文本之间是有点击死区的,容易让人根绝是悬停到了不同地址的链接。同样,如果对整段文本都使用下划线做标识的话,有增加了阅读难度;如果都没有下划线的话,就削减了 点击暗示。
更坏的是,屏幕阅读器读到这里的时候,会把这里的整段文本(包括标题、图片(还不会告诉你这是个图片,只是读它的 alt)和文本块)都读出来,读完之后才告诉你一声“link”(即 <a> 标签的类型)。
如下所示,是另外两个类型的链接的结构:
<!-- 第二个例子 -->
<article style="position: relative;">
<h3><a href="https://example.com/heading">Only on Heading</a></h3>
<img src="https://www.fillmurray.com/600/380" alt="Bill Murray in a still from Caddyshack.">
<p>
Tumeric prism tattooed ... slow-carb unicorn.
</p>
</article>
<!-- 第三个例子 -->
<article style="position: relative;">
<a href="https://example.com/linkwrap" rel="nofollow">
<h3>Wrapping Entire Thing</h3>
<img src="https://www.fillmurray.com/640/360" alt="Bill Murray on the award carpet.">
<p>
Sriracha actually ... party flannel.
<a href="https://example.com/text" rel="nofollow" aria-describedby="A3">Read more…</a>
</p>
</a>
</article>
<style>
a[href]::after {
content: "";
/* 译注:
这一句其实不需要,元素 pos absolute 后,会自动呈现块状元素特性
这里为了显式体现是个 block 元素,就不删除了
*/
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
一个链接包在了 <h3> 里,另一个则包在了段落元素 <p> 中。第三个例子我使用了 aria-describedby 将链接描述指向了 <h3>。这两种形式的链接就是今天我们要介绍的解决方案——就是 positoin: ablsolute 将链接的可点击范围充满整个卡片空间,当然,这可能不是最好的方案。
说到这里,就要讲开发者中存在的一个误解——认为屏幕阅读器用户在页面上浏览内容时只使用 Tab 键,而忘记了实际上的主要方式—箭头(或是在触摸设备上的滑动)。
下面是上述示例,使用箭头(arrow)浏览内容时的效果。
Arrowing through the content in Firefox 72 with NVDA 2019.3.1.
针对第一种链接类型,屏幕阅读器会把每块文本都被声明成链接,这很容易让用户迷惑这些是否都指同一个链接。也许只有那些有经验的用户才能识别出出来,知道它们指的都是同一个地方。相对来说,后面两个的块链接效果就相对好一些。
块链接的 CSS 实现比较简单:
a[href]::after {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
需要注意的是,这种方法实现的块链接会阻止文本选择。
Heydon Pickering 在《Inclusive Components 中的卡片组件》一文中,也对这里的内容作了类似的讨论,但没有给出屏幕阅读器的例子。
变体
我经常被问到这种方式带来的两个挑战。一个是内容顺序(Content order),还有一个是额外控件(additional controls)。
内容顺序
我认为最好能够使用标题来组织内容(其后的内容都是对这个标题的描述),一些开发人员可能不知道如何标记视觉上,图片位于标题之上的设计。说起来,像在卡片组件中出现的图片,本质还是为卡片的标题和文本环境服务的。因此,为了突出内容中心,结构上我总是把标题放在组件中的第一位。
那如何实现,图片视觉上的超前呢。我会使用 Flex 项目的 order 属性来实现,这也是算是我主张的、使用 CSS 对内容重新排序以实现视觉设计需求的少数用例之一。
.card {
display: flex;
flex-direction: column;
}
.card img {
order: -1;
}
额外控件
如果需要在卡片中添加其他链接、按钮或其他控件,要把它放在卡片底部或顶部(甚至沿着侧变),这是同样可以通过预留空间来解决。代码类似于下面这样:
a[href]::after {
bottom: 3.75em;
}
/* <p> 标签里的 <a> 不需要扩大可点击区域 */
p a[href]::after {
content: none;
}
效果如下:
开发工具显示了块链接的可点击区域,在底部留有了一些空白
在图片下面我们保留了一些空白,这可以帮助我们避免误点击/轻击到上面的链接内容。
按钮
你在上面学到的大部分内容也适用于 <button> 标签。仪表板页面通常会包含类似于卡片的界面组件,而且这些往往会包含一个 <button>。
与 <a> 标签不同的是,你可以在 <button> 中嵌套标题、列表(不管有所少)等其他元素,这些结构元素嵌套在<button> 里后,便不再具备结构特性。比如,<button> 中 <h3> 不再具有标题含义了,而是变成了一段普通文本。
以下面代码为例:
<button type="button" onclick="alert('You look nice in those shoes.');">
<h3>Wrapping Entire Thing</h3>
<p>
Hundreds of ... pale blue dot?
</p>
<p>
<span>Settings</span>
</p>
</button>
<section style="position: relative;">
<h3>Only on Settings Text</h3>
<p>
Hundreds of ... pale blue dot?
</p>
<button type="button" class="btn" onclick="alert('You look nice in that shirt.');">
<span>Settings</span>
</button>
</section>
<style>
.btn::after {
content: "";
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
屏幕阅读器的阅读效果如下:
下面是使用箭头浏览 <button> 的效果,与上面一样。
使用屏幕阅读的用户可能对只读出“Settings”的控件就够了。即使感觉困惑,返回或跳转到前面的标题以获得所需的上下文的过程也是简单和快捷的。
上面讲到的块链接样式在这里也同样适用。甚至对按钮中还包含图像或其他的什么控件的情况,也同样适用。
Demo
上面讲过的所有示例代码在下面的 codepen 笔记中都能找到,你可以直接点击查看代码运行效果,也可以使用自己模拟辅助设备环境对它进行调试。
(正文完)
广告时间(长期有效)
我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个爱猫人士并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。
(完)