本文最初出现在包含组件上。如果您想更多地了解类似的包含组件文章,请在Twitter上关注@inclusicomps或订阅RSS源。通过在Patreon上支持inclusive-components.design,您可以帮助它成为可用的强大的界面组件最全面的数据库。
有些东西是开或关,当这些东西不开(或关))时,它们总是关闭(或关闭)。这个概念是如此的简单,我只是通过尝试解释它来复杂化,但是开/关开关(或切换按钮)并不都是一样的。虽然他们的目的很简单,但它们的应用和形式却有很大差异
在这个首播中,我将探讨如何使切换按钮包含在内。与任何组件一样,没有一种方法可以解决这个问题,特别是在不同环境下对这些控件进行了检查时。但是,确实有很多东西要忘记做或者其他的操作,所以我们尽量避免这样做。
改变状态链接
如果Web应用程序根据其用户的指示没有更改,则所得到的经验将完全不令人满意。尽管如此,能够使Web文档能够立即增加自己的奢侈品,而无需再次刷新页面,并不总是存在。
不幸的是,在某个地方,我们决定,可访问的网页只是那些发生很少的静态文档,纯粹被设计为阅读。因此,我们没有努力使网络应用程序更丰富,有状态的包容性。
一个流行的误解是屏幕阅读器不了解 JavaScript。这不仅是完全不真实的 – 所有主要的屏幕阅读器都会对DOM中的变化做出反应,但是在视觉上和辅助技术软件之间传达的基本状态变化并不一定依赖于JavaScript。
复选框和收音机按钮链接
表单元素是互动网页的基本元素,我们不直接使用它们,我们应该密切关注它们的行为。他们处理国家变化已经建立了可用性约定,我们将会愚蠢地忽略它。
可以说,这种checkbox
类型的开箱即用的输入是完全可以使用的开/关开关。如果标签正确,它具有可访问控制的所有基本要素:屏幕阅读器和键盘可在平台和设备之间访问,并传达其状态更改(检查为未选中,反之亦然),而无需重新构建整个文档。
在以下示例中,复选框用作电子邮件通知设置的切换。
<input type="checkbox" id="notify" name="notify" value="on">
<label for="notify">Notify by email</label>
屏幕阅读器软件在对此控件的解释方面相当统一。在重点控制(使用Tab键移动到它)时,将会公布类似的“通过电子邮件通知,复选框未选中”。这就是所有的标签,角色和状态信息。
检查复选框后,大多数屏幕阅读器软件将会立即通知已更改的状态“已检查”(有时也会重复标签和角色信息)。没有JavaScript,我们已经处理了状态,屏幕阅读器软件能够反馈给用户。
屏幕阅读器不仅适用于盲链
有些操作屏幕阅读器来帮助他们了解界面。其他人可能是视觉上的阅读障碍或识字率低的。甚至有些身体或认知困难的人理解一个界面,他们只是喜欢把它读出来给他们。
支持屏幕阅读软件支持屏幕阅读软件,不盲人。屏幕阅读器是很多不同人喜欢使用的工具。
在这种情况下,开关的开/关部分不通过标签而是通过状态。相反,标签是用于识别我们关闭或打开的东西。研究表明,用户从更明确的开/关隐喻中受益,可以使用单选按钮组。
<fieldset>
<legend>Notify by email</legend>
<input type="radio" id="notify-on" name="notify" value="on" checked>
<label for="notify-on">on</label>
<input type="radio" id="notify-off" name="notify" value="off">
<label for="notify-off">off</label>
</fieldset>
组标签是一个强大的工具。顾名思义,他们可以为相关(分组)项目提供单一标签。在这种情况下,<fieldset>
组元素与元素一起工作,<legend>
以将组标签“通过电子邮件通知”提供给单选按钮。这些按钮是通过共享一个name
属性值来形成的,这样可以使用箭头键在它们之间切换。HTML语义不仅仅是添加信息,而且还会影响行为。
在Windows屏幕读取器JAWS和NVDA中,当用户对第一个控件进行聚焦时,组标签将被添加到该控件的单个标签中,并且列出了分组的单选按钮。在NVDA中,附加了术语“分组”,使事情更加明确。在上面的例子中,聚焦第一个(默认选中的)单选按钮,引出“通过电子邮件通知,分组,单选按钮,检查,两个之一”。
现在,尽管检查状态(在一些屏幕阅读器中宣布为“选择”)仍然被切换,但我们真正允许用户在“开”和“关”之间切换。那些是组合控制的两个可能的词汇状态,如果你愿意的话。
样式表单元素链接
表单元素众所周知难以设计风格,但是我们在“ 替换单选按钮而不替换单选按钮”中写道,它有很好的CSS技术来设计收音机和复选框。有关如何选择元素和文件输入的提示,请参阅WTF表单?由马克奥托。
这听起来不是很正确的LINK
复选框和单选按钮实现都可以作为开/关控件。毕竟,它们可以通过不同设备,浏览器和操作系统上的鼠标,触摸,键盘和辅助技术软件访问。
但可访问性只是包容性设计的一部分。这些控制也必须对用户有意义 ; 他们必须在界面中发挥明确的作用。
使用表单元素的麻烦是与数据收集的长期关联。也就是说,复选框和单选按钮被建立为用于指定值的控件。当用户检查复选框时,他们可能只是切换状态,但他们可能会怀疑他们也在选择提交的值。
无论您是看着复选框的用户,屏幕阅读器用户都会听到其身份被宣布,或者是两者,它的词源都是有问题的。我们希望切换按钮是按钮,但复选框和单选按钮是真正的输入。
真切换按钮链接
有时我们使用<button>
元素来提交表单。为了完全符合和可靠,这些按钮应该type
取值submit
。
<button type="submit">Send</button>
但这些只是一种按钮,涵盖一个用例。事实上,<button>
元素可以用于各种各样的事物,而不仅仅是与形式相关联。他们只是按钮。我们提醒自己这个,给他们的type
价值button
。
<button type="button">Send</button>
通用按钮是用于更改界面内的任何内容(使用JavaScript而不重新加载页面)的转移元素,除了文档之间和之间的位置,这是链接的权限。
在链接旁边,按钮应该是您在Web应用程序中最多见的互动元素。他们预先打包“按钮”角色,默认情况下可以访问键盘和屏幕阅读器。与某些形式元素不同,它们也是微不足道的风格。
那么我们如何做<button>
一个切换按钮?这是使用WAI-ARIA作为逐步增强的一种情况。WAI-ARIA提供在基本HTML中不可用的状态,例如按下状态。想象一下电脑的电源开关。当它被按下或被推入 – 表示计算机处于其“开”状态时。当它没有打开 – 戳出来 – 电脑必须关闭。
<button type="button" aria-pressed="true">
Notify by email
</button>
WAI-ARIA状态属性像aria-pressed
布尔类似,但与标准的HTML状态属性不同,checked
它们必须具有true
或者的显式值false
。只是添加aria-pressed
不可靠。而且,没有属性意味着未被压制的状态不会传达(没有属性的按钮只是通用按钮)。
您可以根据需要在表单或外部使用此控件。但是如果您在表单中使用它,则该type="button"
部分很重要。如果不在那里,一些浏览器将默认为隐式type="submit"
并尝试提交表单。您不必event.preventDefault()
在type="button"
控件上使用来禁止提交表单。
将状态从true
(on)切换到false
(关闭)可以通过一个简单的点击处理程序完成。由于我们使用a <button>
,可以通过鼠标点击,按Space或Enter键或通过触摸屏点击按钮来触发此事件类型。对每个这些动作的响应<button>
都是标准的内容。如果您参考HTMLButtonElement界面,您将看到其他属性(例如)disabled
也即将开箱即用。在<button>
不使用元素的地方,这些行为必须用定制脚本来模拟。
const toggle = document.querySelector('[aria-pressed]');
toggle.addEventListener('click', (e) => {
let pressed = e.target.getAttribute('aria-pressed') === 'true';
e.target.setAttribute('aria-pressed', String(!pressed));
});
更清晰的状态链接
当aria-pressed
某些屏幕阅读器遇到具有状态的按钮时,会发生一个有趣的事情:它被标识为“切换按钮”,或者在某些情况下被标识为“按钮”。状态属性的存在会更改按钮的身份。
当aria-pressed="true"
使用NVDA 对示例按钮进行对焦时,屏幕阅读器会宣布“通过电子邮件通知,切换按钮,按下”。“按”状态比“检查”更加容易,加上我们避开表单数据输入内容。当点击按钮时,立即反馈以“未按下”的形式提供。
样式链接
我们构建的HTML是我们所做的设计工作和我们为网络创建的事物的重要组成部分。我非常信任HTML First Prototyping™,确保了风格和品牌产品的坚实基础。
在我们的切换按钮的情况下,该基础包括使按钮与各种输入(例如语音激活软件)和输出(例如,屏幕阅读器)设备互操作的语义和行为。可以使用HTML,但需要CSS来使控件可视化。
表单应该遵循功能,这在CSS中很容易实现:我们的HTML中的所有内容使我们的简单的切换按钮功能也可以用于表单。
<button>
→button
元素选择器aria-pressed="true"
→[aria-pressed="true"]
属性选择器。
在一个一致的,因此,易于理解的界面,按钮应该分享一定的外观。按钮都应该看起来像按钮。因此,我们的基本切换按钮样式应该可以从button
元素块继承:
/* For example... */
button {
color: white;
background-color: #000;
border-radius: 0.5rem;
padding: 1em 2em;
}
有几种方式我们可以视觉地表示“按下”。字面解释,我们可以使按钮的外观在按下使用一些插图box-shadow
。我们为此使用属性选择器:
[aria-pressed="true"] {
box-shadow: inset 0 0 0 0.15rem #000,
inset 0.25em 0.25em 0 #fff;
}
要完成按压/未压缩的比喻,我们可以使用一些定位,box-shadow
并使未按下的按钮“捅出”。该块应该出现[aria-prressed="true"]
在级联中的块上方。
[aria-pressed] {
position: relative;
top: -0.25rem;
left: -0.25rem;
box-shadow: 0.125em 0.125em 0 #fff,
0.25em 0.25em #000;
}
(注意:这种造型方法只是一个想法,您可能会发现更明显的东西,比如在使用“on”/“off”标签的例子中可以看到更多的用户。)
不要依靠颜色单独链接
“开”通常用绿色表示,红色表示“关”。这是一个既定的惯例,并没有包含它的危害。但是,请注意不要*只使用颜色来描述按钮的两个状态。如果你这样做,一些色盲用户将无法区分它们。
聚焦风格
重要的按钮以及所有交互式组件都具有焦点样式。否则键盘导航的人无法看到哪些元素处于控制状态并且可以运行。
最佳对焦风格不会影响布局(界面在元素之间移动时不应该分心)。通常情况下,人们会使用outline
,但是outline
在大多数浏览器中只能使用一个框。为了适应我们按钮的弯曲角落的焦点风格,a box-shadow
更好。由于我们已经使用box-shadow
了,我们必须要小心点:注意box-shadow
在按压和重点关注状态下的两个逗号分隔的样式。
/* Remove the default outline and
add the outset shadow */
[aria-pressed]:focus {
outline: none;
box-shadow: 0 0 0 0.25rem yellow;
}
/* Make sure both the inset and
outset shadow are present */
[aria-pressed="true"]:focus {
box-shadow: 0 0 0 0.25rem yellow,
inset 0 0 0 0.15rem #000,
inset 0.25em 0.25em 0 #fff;
}
更改标签链接
之前的切换按钮设计有一个独立的,独特的标签,并区分其两个状态,使用引起风格的归因变化。如果我们想创建一个将标签从“开”更改为“关闭”或“播放”到“暂停”的按钮,该怎么办?
在JavaScript中很容易做到这一点,但有一些我们需要注意的事情。
- 如果标签发生变化,国家会怎样?
- 如果标签只是“开”或“关”(“播放”或“暂停”,“活动”或“不活动”),我们如何知道按钮实际控制?
在上一个切换按钮示例中,标签描述了什么是开或关。在“什么”部分不一致的情况下,很快就会出现混乱:一旦“关闭”/未压缩已经变成“打开”/按下,我必须打开“打开”按钮才能打开“关闭”按钮。什么?
作为经验法则,您不应该将压缩状态和标签一起更改。如果标签发生变化,按钮在某种意义上已经改变了状态,而不是通过显式的WAI-ARIA状态管理。
在以下示例中,只有标签更改。
const button = document.querySelector('button');
button.addEventListener('click', (e) => {
let text = e.target.textContent === 'Play' ? 'Pause' : 'Play';
e.target.textContent = text;
});
这种方法的问题是标签更改不会因为发生而公布。也就是说,当您点击播放按钮时,相当于“按”的反馈不存在。相反,您必须手动对焦并重新对焦按钮以听到它已更改。对于目视用户来说,这并不是一个问题,而对于盲人阅读器用户而言,它们的人体工程学较少
播放/暂停按钮通常在播放符号(侧面的三角形)和暂停符号(两条垂直线)之间切换。我们可以做到这一点,同时保持一致的非视觉标签和变化的状态。
<!-- Paused state -->
<button type="button" aria-pressed="false" aria-label="play">
▶
</button>
<-- Playing state -->
<button type="button" aria-pressed="true" aria-label="play">
⏸
</button>
因为aria-label
覆盖了unicode符号文本节点,所以暂停的按钮被宣布为类似于“播放按钮,未按下”,播放按钮为“播放按钮,按下”。
这是非常好的,除了语音识别和激活的地方。在语音识别软件中,您通常需要通过发出标签来识别按钮。如果用户看到一个暂停符号,他们的第一个倾向是说“暂停”,而不是“播放”。因此,切换标签而不是状态在这里更加强大。
辅助标签链接
在某些情况下,我们可能希望提供实际读取“开/关”的开/关开关。这些技巧是确保每个拨动开关和相应的辅助标签之间有明确的关联。
想象一下,电子邮件通知设置与列表中的其他类似设置一起分组。每个列表项都包含一个接通/关闭开关的设置描述。开/关开关使用术语“开”和“关”作为其设计的一部分。<span>
为样式提供了一些元素。
<h2>Notifications</h2>
<ul>
<li>
Notify by email
<button>
<span>on</span>
<span>off</span>
</button>
</li>
<li>
Notify by SMS
<button>
<span>on</span>
<span>off</span>
</button>
</li>
<li>
Notify by fax
<button>
<span>on</span>
<span>off</span>
</button>
</li>
<li>
Notify by smoke signal
<button>
<span>on</span>
<span>off</span>
</button>
</li>
</ul>
列表的优点是,视觉上和非视觉上,它们将项目组合在一起,显示它们是相关的。这不仅有助于理解,还可以在一些屏幕阅读器中列出导航快捷方式。例如,JAWS提供在列表和列表之间移动的L(列表)和I(列表项)快捷键。
每个“标签”和按钮都属于一个共同的列表项。然而,没有提供明确的,独特的标签是危险的领域 – 特别是在语音识别方面。使用aria-labelledby
,我们可以将每个按钮与列表的文本相关联:
<h2>Notifications</h2>
<ul>
<li>
<span id="notify-email">Notify by email</span>
<button aria-labelledby="notify-email">
<span>on</span>
<span>off</span>
</button>
</li>
<li>
<span id="notify-sms">Notify by SMS</span>
<button aria-labelledby="notify-sms">
<span>on</span>
<span>off</span>
</button>
</li>
<li>
<span id="notify-fax">Notify by fax</span>
<button aria-labelledby="notify-fax">
<span>on</span>
<span>off</span>
</button>
</li>
<li>
<span id="notify-smoke">Notify by smoke signal</span>
<button aria-labelledby="notify-smoke">
<span>on</span>
<span>off</span>
</button>
</li>
</ul>
每个aria-labelledby
值匹配适当的跨度id
,形成关联并给予按钮其唯一的标签。它的作用很像一个<label>
元素的for
属性,标识一个字段id
。
交换角色
重要的是,ARIA标签会覆盖每个按钮的文本内容,这意味着我们可以再次使用aria-pressed
通信状态。然而,由于这些按钮是明确的“开/关”开关,所以我们可以改用WAI-ARIA切换角色,通过它来传达状态aria-checked
。
<h2>Notifications</h2>
<ul>
<li>
<span id="notify-email">Notify by email</span>
<button role="switch" aria-checked="true" aria-labelledby="notify-email">
<span>on</span>
<span>off</span>
</button>
</li>
<li>
<span id="notify-sms">Notify by SMS</span>
<button role="switch" aria-checked="true" aria-labelledby="notify-sms">
<span>on</span>
<span>off</span>
</button>
</li>
<li>
<span id="notify-fax">Notify by fax</span>
<button role="switch" aria-checked="false" aria-labelledby="notify-fax">
<span>on</span>
<span>off</span>
</button>
</li>
<li>
<span id="notify-smoke">Notify by smoke signal</span>
<button role="switch" aria-checked="false" aria-labelledby="notify-smoke">
<span>on</span>
<span>off</span>
</button>
</li>
</ul>
你如何设计活跃的状态是相当的取决于你,但我个人将<span>
使用JavaScript 编写类属性到s。相反,我会使用伪类编写一些CSS,以根据状态来定位相关的跨度。
[role="switch"][aria-checked="true"] :first-child,
[role="switch"][aria-checked="false"] :last-child {
background: #000;
color: #fff;
}
遍历设置
现在让我们来谈谈通过这个设置部分使用两种不同的策略:通过Tab键(仅在可重点的元素之间跳转)和屏幕阅读器浏览(移动每个元素)。
即使通过Tab键进行导航,不仅仅是屏幕阅读器中宣布的交互式元素的身份和状态。例如,当您第一个关注时<button>
,您会听到它是一个带有“通过电子邮件通知”标签的开关,处于开启状态。“开关”是角色,aria-checked="true"
并被称为“开”,这个角色是存在的。
切换角色支持
这个switch
角色不是很受支持aria-pressed
。例如,Chrome浏览器的ChromeVox屏幕阅读器扩展程序无法识别。
然而,ChromeVox的不支持aria-checked
。这意味着,而不是“通过电子邮件发送,通知”正在被宣布,“按钮,通过电子邮件通知,检查”代替。这不是令人回味,但它是足够的。更有可能的是,它只会被误认为是一个复选框输入。
奇怪的是,NVDA 在按下状态时会看到一个按钮,role="switch"
并且aria-checked="true"
作为一个切换按钮。由于开/关并按压/未压缩是等同的,这是可以接受的(虽然有点
令人失望)。
但是,在大多数屏幕阅读器中,您还将被告知您已经输入了四个项目的列表,并且您在第一个项目 – 有用的上下文信息有点像我在本文前面所述的组标签。
重要的是,因为我们曾经aria-labelledby
将相邻的文本与按钮相关联,也可以在此模式下导航。
当从项目浏览(例如,当NVDA屏幕阅读器运行时按下向下键),您会遇到的所有内容都会公布,包括标题(“通知,标题二级”)。当然,以这种方式浏览,“通过电子邮件通知”是自己宣布的,并且与相邻按钮相关联。这有点重复,但有意义:“这是设置名称,这里是设置此名称的开/关开关。
您需要如何明确地将控件与其控制的内容相关联,这是UX设计的一个更精细的点,值得考虑。在这种情况下,我们保留了经过视觉用户的经典开/关开关,无论使用哪种键盘交互模式,都不会让盲人或视力的屏幕阅读器用户混淆或误导。这很健壮
结论链接
您如何设计和实现切换按钮是相当理想的,但是希望在将这个特定的组件添加到模式库时,您会记住这个帖子。没有理由为什么切换按钮 – 或任何接口组件,这样的事情 – 应该边缘化他们经常做的人数。
您可以参考这里探索的基础知识,并添加各种设计细节,包括动画。奠定坚实的基础是重要的。
清单链接
- 如果您确定用户不会相信他们提交数据,请使用表单元素(如复选框)进行开/关切换。
- 使用
<button>
元素,而不是链接,aria-pressed
或aria-checked
。 - 不要一起改变标签和状态。
- 当使用视觉“开”和“关”文本标签(或类似)时,您可以通过使用唯一的标签来覆盖这些标签
aria-labelledby
。 - 小心确保按钮的文本和背景颜色之间的对比度水平符合WCAG 2.0的要求。