简体   繁体   English

向屏幕阅读器宣布某些文本的最佳方式是什么(即 role="alert", aria-live="assertive/polite")?

[英]What is the best way to announce some text to screen readers (ie. role="alert", aria-live="assertive/polite")?

I'm in the process of creating a searchable combobox component.我正在创建一个可搜索的 combobox 组件。 It must be 100% accessible, so I want to tell screen readers how many results there are available when they open the component's options dropdown, and when they are changing its filter term.它必须是 100% 可访问的,所以我想告诉屏幕阅读器在他们打开组件的选项下拉列表时以及在更改其筛选条件时有多少结果可用。

The component looks something like this:该组件看起来像这样:

成分

I think I will probably need a live region.我想我可能需要一个现场区域。 I know two ways of doing this:我知道有两种方法可以做到这一点:

1) role="alert" 1) role="alert"

This is AFAIK the safest option: it used to work years ago already, and it is pretty well supported by all major browsers (Chrome/Edge, FF) and screen readers (JAWS, NVDA, VoiceOver/iOS, Talkback).这是 AFAIK 最安全的选择:它在几年前就已经可以工作了,并且得到了所有主要浏览器(Chrome/Edge、FF)和屏幕阅读器(JAWS、NVDA、VoiceOver/iOS、Talkback)的良好支持。

The bad thing: it is "rude", ie.坏事:它是“粗鲁的”,即。 it interrupts the screen reader's current announcement.它会打断屏幕阅读器的当前通告。 In addition, some browsers add an ugly "Alert" as a prefix to each such announcement.此外,某些浏览器会在每个此类公告中添加一个丑陋的“Alert”作为前缀。

So for example, if the options dropdown is expanded (the user presses Down key after focusing the filter input), then two things happen at the same time:因此,例如,如果选项下拉列表被展开(用户在聚焦过滤器输入后按下Down键),则同时发生两件事:

  • The filter input's aria-expanded is set from false to true , which makes the screen reader announce expanded过滤器输入的aria-expandedfalse设置为true ,这使得屏幕阅读器宣布expanded
  • The dropdown is now visible, containing a live region with text 4 of 12 options available, starting with "Badminton"下拉菜单现在可见,包含一个实时区域,其中4 of 12 options available, starting with "Badminton"

If this live region is a role="alert" , then it potentially interrupts (⚡️) the expanded announcement, which feels like a hiccup from the screen reader, ie.如果这个实时区域是一个role="alert" ,那么它可能会中断 (⚡️) expanded的公告,这感觉就像屏幕阅读器的一个小问题,即。 expa⚡️ 4 of 12 options... . expa⚡️ 4 of 12 options... .

2) aria-live="polite" 2) aria-live="polite"

This is the more gentle option: it will append the live region's content to the current announcement of the screen reader (instead of interrupting it), ie.这是更温和的选项:它将 append 实时区域的内容添加到屏幕阅读器的当前公告(而不是中断它),即。 expanded 4 of 12 options... . expanded 4 of 12 options...

Sadly, this is not supported with JAWS+Chrome, as far as my tests show - can anyone confirm this?遗憾的是,据我的测试显示,JAWS+Chrome 不支持这一点——有人能证实这一点吗? If so, this is extremely lame, taking into account that its the most used desktop combination, and behind both are multi-national (and probably multi-billion) companies.如果是这样,那就太蹩脚了,考虑到它是最常用的桌面组合,而且两者背后都是跨国公司(可能还有数十亿)。

Conclusion结论

I can't just use the gentle aria-live everywhere, I need to figure out which browser is used, and if it's Chrome, I need to reside to role="alert" .我不能到处使用温和的aria-live ,我需要弄清楚使用的是哪个浏览器,如果是 Chrome,我需要驻留在role="alert"

But there are more problems: there seem to be serious differences between how browsers (and/or screen readers) handle live regions:但还有更多问题:浏览器(和/或屏幕阅读器)处理实时区域的方式似乎存在严重差异:

  • Some have problems recognising a live region if it's first hidden (ie. hidden attribute, or display: none ) and then made visible.如果它首先hidden (即hidden属性,或display: none )然后变得可见,有些人在识别活动区域时会遇到问题。 It will then simply not be treated as live region.然后它就不会被视为活动区域。
  • Some immediately announce the content of such a made-visible live region, while others just ignore their initial content (they will only announce a change to it).有些人会立即宣布这种可见的直播区域的内容,而另一些人则只是忽略他们的初始内容(他们只会宣布对其进行更改)。
  • Some announce a role="alert" element even when it's already there when the page is loaded, others don't (and I think the latter ones are right, because as far as I understand, live regions should announce changes of content, not content that's initially there already)有些人宣布一个role="alert"元素,即使它在页面加载时已经存在,其他人则没有(我认为后者是正确的,因为据我所知,实时区域应该宣布内容的变化,而不是最初已经存在的内容)

So this topic is much more complex than I hoped.所以这个话题比我希望的要复杂得多。 The simplest solution would probably be the following: just append a visually hidden role="alert" element at the end of the DOM each time an announcement is be made.最简单的解决方案可能如下所示:每次发布公告时,只需 append 在 DOM 末尾添加一个视觉上隐藏的role="alert"元素。 Then, a few seconds later, remove it again.然后,几秒钟后,再次将其取下。 But this feels ugly to me.但这对我来说很难看。 I'd rather have my live region right inside my component, where also visible users can see it, or at least parts of it: on the screenshot you can see 4 of 12 options for filter "d" , but to screen readers, the same text is announced, plus some more details, ie.我宁愿让我的活动区域就在我的组件内部,可见用户也可以看到它,或者至少看到它的一部分:在屏幕截图上,您可以看到4 of 12 options for filter "d" ,但对于屏幕阅读器来说,宣布了相同的文本,加上一些更多的细节,即。 starting with option "Badminton" . starting with option "Badminton" Keeping visual and screen reader announcement in the same place feels like good practice to me, so I will not easily forget about the latter ones, or I will spot some bugs quickly (that would otherwise may be not visible).将视觉和屏幕阅读器公告放在同一个地方对我来说是一种很好的做法,所以我不会轻易忘记后者,否则我会很快发现一些错误(否则可能不可见)。

So my question is: is there maybe an existing script or library which solves this problem in a solid way and provides optimal experience for the most common browser / screen reader combos?所以我的问题是:是否有现有的脚本或库可以可靠地解决这个问题并为最常见的浏览器/屏幕阅读器组合提供最佳体验?

Thank you.谢谢你。

Polite live regions should be preferred.礼貌的居住地区应该是首选。 As you have noticed yourself, alert interrupts current speech, it's rude.正如您自己注意到的那样,警报会打断当前的讲话,这很不礼貌。 The prefix "Alert."前缀“警报”。 automatically added might even feel a little scary at times.自动添加有时甚至会让人感到有点害怕。

As you have noticed, polite live regions are working a little different on each browser + screen reader combinations.正如您所注意到的,礼貌的实时区域在每个浏览器 + 屏幕阅读器组合上的工作方式略有不同。 Some of these differences are intentional, others are just bugs, and others are simply due to the fact that the official specification doesn't clearly define any particular behavior.其中一些差异是有意为之,另一些只是错误,还有一些仅仅是因为官方规范没有明确定义任何特定行为。 This makes the whole thing, as you have said, actually quite complicated.正如你所说,这使得整个事情变得非常复杂。 Sadly I have no universally working solution.遗憾的是,我没有通用的解决方案。 In order to handle all cases, you need to make user agent detection.为了处理所有情况,您需要进行用户代理检测。

Let's look at various issues or points of attention we have with live regions today (in may 2022).让我们看看今天(2022 年 5 月)我们在实时区域中遇到的各种问题或注意点。 I have no official reference, the following is only my own observations along the years:我没有官方参考,以下仅是我多年来的观察:

Live region detection实时区域检测

A live regions is successfully taken into account as such only when aria-live attribute is present when the element is added to the DOM , and when it is visible by screen readers .只有当元素添加到 DOM 时存在 aria-live 属性并且屏幕阅读器可见时,才会成功考虑活动区域。

This, in particular, means that it isn't taken into account when the aria-live attribute is set after the element has been added in the DOM, when the element is display:none, visibility:hidden, when attributes aria-hidden or hidden are set, or when the size is 0. Even if hidding attributes are removed later on, it doesn't work.特别是,这意味着在将元素添加到 DOM 后设置 aria-live 属性时,当元素显示:无,可见性:隐藏时,当属性 aria-hidden 或hidden 被设置,或者当 size 为 0 时。即使稍后删除 hidding 属性,它也不起作用。

Announcement time公示时间

The only two cases when the content of a live region has to be announced are:必须公布直播区域内容的仅有两种情况是:

  • When the element is added in the DOM当元素被添加到 DOM 中时
  • When the content of the element has changed当元素的内容发生变化时

For all other cases, it isn't well defined in the specification.对于所有其他情况,规范中没有明确定义。 In particular, initial content present directly in HTML code may not be announced, and as far as I have already observed, none of the browsers I have already used ever announce initial content at page load.特别是,直接出现在 HTML 代码中的初始内容可能不会被公布,据我观察,我使用过的浏览器都没有在页面加载时公布初始内容。

Interruptions中断

When an assertive live region is added, speech is normally always interrupted.当添加一个自信的现场区域时,语音通常总是被打断。 Polite live regions updates should never interrupt speech.礼貌的实时区域更新不应打断语音。

However, with many browsers + screen readers combinations, a content currently being read is shut up:但是,对于许多浏览器+屏幕阅读器的组合,当前正在阅读的内容会被关闭:

  • When the aria-live element is removed from the DOM当 aria-live 元素从 DOM 中移除时
  • When its content is emptied当它的内容被清空时

This is for example the case with VoiceOver both under iOS and mac.例如,iOS 和 mac 下的 VoiceOver 就是这种情况。

So if you have multiple messages to be spoken potentially quick in succession, you shouldn't just replace the older message by the newer one.因此,如果您有可能连续快速地说出多条消息,则不应只用新消息替换旧消息。 You can adopt several strategies:您可以采用几种策略:

  • Simply append new messages to the already existing live region只需 append 条新消息到现有的实时区域
  • Create new live regions each time每次创建新的活动区域
  • Clear live region content or remove it from the DOM only if the last messages is older than a few seconds ago仅当最后一条消息早于几秒前时,才清除实时区域内容或将其从 DOM 中删除

But, be careful, that's not all.但是,请注意,这还不是全部。

Repeat or not repeat重复或不重复

With some browsers + screen readers combinations, if you simply append new messages to be announced at the end of a live region, the whole content is repeated over and over again from the beginning.对于某些浏览器 + 屏幕阅读器组合,如果您只是在直播区域的末尾宣布 append 条新消息,则整个内容从头开始一遍又一遍地重复。 In short, the whole content is read each time there is a change, even parts that haven't changed.简而言之,每次有变化时都会阅读整个内容,即使是没有变化的部分。

IN theory, the standard provides the two attributes aria-atomic and aria-relevant to control this behavior.理论上,该标准提供了两个属性aria-atomicaria-relevant来控制这种行为。 Defaults values are aria-atopic=false and aria-relevant=additions, meaning that only the new content has to be read, and content that hasn't changed shouldn't be read again.默认值是 aria-atopic=false 和 aria-relevant=additions,这意味着只有新内容必须被阅读,没有改变的内容不应该被再次阅读。

However, in practice:然而,在实践中:

  • Chrome with both Jaws and NVDA ignore these attributes completely.带有 Jaws 和 NVDA 的 Chrome 完全忽略了这些属性。 The whole content is always read at every change no matter what.无论如何,每次更改时都会阅读全部内容。
  • With Firefox and Jaws, the aria-live region no longer works when aria-relevant attribute is explicitly set使用 Firefox 和 Jaws,当显式设置 aria-relevant 属性时,aria-live 区域不再有效
  • With at least some versions of Safari, the aria-live region doesn't work if aria-relevant=additions isn't explicitly set对于 Safari 的至少某些版本,如果未明确设置 aria-relevant=additions,aria-live 区域将不起作用
  • With some versions of Chrome, if for any reason you want to speak twice the same message, replacing content doesn't work, even if you replace first by the empty string and then by the content again在某些版本的 Chrome 中,如果出于任何原因你想说两次相同的消息,替换内容是行不通的,即使你首先替换为空字符串,然后再替换为内容

Are we safe if we create a new live region for each message?如果我们为每条消息创建一个新的活动区域,我们是否安全? Spoiler alert: no!剧透警报:不!

Announcement order公告顺序

When several live regions are added to the DOM or updated quickly, nothing says which one has to be announced first.当多个实时区域被添加到 DOM 或快速更新时,没有人说必须首先宣布哪个。

  • Safari iOS seem to handle it correctly, ie read content in the order of update. Safari iOS 似乎处理正确,即按更新顺序读取内容。 I don't know on mac.我不知道在 mac 上。
  • With Chrome and both Jaws and NVDA, updating quickly several live regions seem to make them being read in reverse order of their position in the DOM.使用 Chrome 以及 Jaws 和 NVDA,快速更新几个活动区域似乎使它们在 DOM 中以与 position 相反的顺序读取。

Conclusion结论

At present, it looks like the safest is to create new polite live regions for each message.目前,看起来最安全的是为每条消息创建新的礼貌生活区域。 You can reuse them, but only if new messages don't arrive too quickly, or if it doesn't matter if they are occasionally interrupted.您可以重复使用它们,但前提是新消息不会很快到达,或者它们偶尔被打断也没关系。

For your particular case, I would say that a single reused polite live region is sufficient.对于您的特殊情况,我会说一个重复使用的礼貌活动区域就足够了。 But of course the best is to test as many combinations as possible.但当然最好的办法是测试尽可能多的组合。

Good luck.祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Firefox上,有没有aria = live =“ assertive”没有role =“ alert”的方法吗? - Is there any way for aria-live=“assertive” without role=“alert” on Firefox? 从屏幕阅读器隐藏Aria-live(礼貌)内部div中的内容更改 - Hide content changes in div inside Aria-live ( polite ) from Screen readers 辅助功能:JAWS 不会为 *ngIf 发音 aria-live 礼貌或自信 - Accessibility: JAWS doesn't pronounce aria-live polite or assertive for *ngIf aria-live =“礼让”不会宣布选中的表单控件(如单选按钮/复选框) - aria-live=“polite” doesn't announce selected form controls like radio button/checkbox 屏幕阅读器aria live断言文本被打断 - Screen reader aria live assertive text is interrupted 尽管隐藏了 div,但仍宣布 aria-live 文本更改 - Announce aria-live text change despite div being hidden 重新宣布一个<p>即使文本相同,在 aria-live 下</p> - re announce a <p> under aria-live even if the text is same 屏幕阅读器如何通过aria-atomic处理嵌套的aria-live - How do screen readers handle nested aria-live with aria-atomic aria-live=“polite” 不读取与其关联的元素的角色 - aria-live=“polite” not reading roles of elements it is associated with 如何对屏幕阅读器隐藏ARIA-LIVE,但使他们可以在其中阅读内容? - How to hide ARIA-LIVE from screen readers but make they will can read content inside?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM