NVDA 屏幕阅读器未读取最新 Chrome 版本的警告消息
NVDA screenreader not reading alert message with latest Chrome version
我在下面创建了 HTML 演示页面。 In that page a message is added to a div when selecting the "No" radiobutton. div 上面有 aria-tags。有问题的 div 的 ID 为“lblErr”/“lblErr2”。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Screenreader Errormessage Test with Radiobuttons</title>
</head>
<body>
<label id="instructionLbl">
Please select below
</label>
<div>
<div id="firstItemGroup">
<label id="headerTextLbl">
Select no to generate the error message
</label>
<fieldset aria-labelledby="headerTextLbl">
<div id="selectionGroup1">
<table id="radioBtnTable">
<tbody>
<tr>
<td>
<label for="button:conf:1">Yes</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="1" id="button:conf:1" name="button:conf" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr');while(errorDiv.hasChildNodes()){errorDiv.removeChild(errorDiv.lastChild);}">
</input>
</div>
</div>
</td>
<td>
<label for="button:conf:2">No</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="2" id="button:conf:2" name="button:conf" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr');errorDiv.style.display = 'block';var newDiv = document.createElement('div');var spanOne = document.createElement('span');spanOne.classList.add('ui-message-error-icon');var spanTwo = document.createElement('span');spanTwo.classList.add('ui-message-error-detail');var errMsg = document.createTextNode('Very long error message with special red font, details, paragraphs and recovery suggestion is displayed here');spanTwo.appendChild(errMsg);newDiv.appendChild(spanOne);newDiv.appendChild(spanTwo);errorDiv.appendChild(newDiv);">
</input>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div id="lblErr" style="display: none;" role="alert" aria-atomic="true" aria-live="polite" tabindex="3"></div>
</div>
</fieldset>
</div>
<div id="subItemsGroup">
<label id="headerTextLbl2">
Label with headertext
</label>
<fieldset aria-labelledby="headerTextLbl2">
<div id="selectionGroup2">
<label id="instructionLbl2">Select no to generate the error message</label>
<table id="radioBtnTable2">
<tbody>
<tr>
<td>
<label for="button:conf:3">Yes</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="4" id="button:conf:3" name="button:conf:2" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr2');while(errorDiv.hasChildNodes()){errorDiv.removeChild(errorDiv.lastChild);}">
</input>
</div>
</div>
</td>
<td>
<label for="button:conf:4">No</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="5" id="button:conf:4" name="button:conf:2" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr2');errorDiv.style.display = 'block';var newDiv = document.createElement('div');var spanOne = document.createElement('span');spanOne.classList.add('ui-message-error-icon');var spanTwo = document.createElement('span');spanTwo.classList.add('ui-message-error-detail');var errMsg = document.createTextNode('Very long error message with special red font, details, paragraphs and recovery suggestion is displayed here');spanTwo.appendChild(errMsg);newDiv.appendChild(spanOne);newDiv.appendChild(spanTwo);errorDiv.appendChild(newDiv);">
</input>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div id="lblErr2" style="display: none;" role="alert" aria-atomic="true" aria-live="polite" tabindex="6"></div>
</div>
</fieldset>
</div>
</div>
</body>
</html>
添加错误信息的JavaScript代码。我将它添加到单选按钮的 onChange 中:
var errorDiv = document.getElementById('lblErr');
var newDiv = document.createElement('div');
var spanOne = document.createElement('span');
spanOne.classList.add('ui-message-error-icon');
var spanTwo = document.createElement('span');
spanTwo.classList.add('ui-message-error-detail');
var errMsg = document.createTextNode('Very long error message with special red font, details, paragraphs and recovery suggestion is displayed here');
spanTwo.appendChild(errMsg);
newDiv.appendChild(spanOne);
newDiv.appendChild(spanTwo);
errorDiv.appendChild(newDiv);
这是我们制作的HTML / JS 的提取和简化版本。在生产中,这些选择中有 5 到 6 个一个在另一个下面,它被嵌入到一个更大的 HTML 结构中(有多个父 divs,它们也有导航元素和其他东西)。
此 HTML 在与 Google Chrome 和 NVDA 屏幕 reader 结合使用时存在问题。在生产中选择“否”选项时,错误消息会添加到 HTML,但 NVDA 根本不会读取任何错误消息。 Firefox 中的相同情况导致 NVDA 读取“警报...”。
以下部分已编辑,请参阅下面的编辑内容。
这个简化的演示片段的行为略有不同。此处 Firefox 两次读取错误消息。一次只有消息文本,然后第二次“警报”,然后是消息文本。 Chrome 只读取一次并忽略以“alert”开头的第二条消息。我只希望它在两种浏览器中都显示为“警报...”。
围绕错误消息的 span 和 div 构造在生产环境和我的代码片段中是相同的。
我的问题是:为什么在 Chrome 中添加消息时 NVDA 不读取“警报...”?这是 HTML 或 Chrome 或 NVDA 的问题吗?我可以通过对 HTML 进行非破坏性更改来修复它吗?
编辑: 我现在编辑了 HTML / JS,这样它就不会读取 Chrome 中的任何错误消息,而它仍然读取它在 Firefox 中。发生变化的是 divs lblErr/lblErr2 现在以“显示:none”样式属性开始,即使我在添加错误消息之前删除了它。所以 Chrome / NVDA 似乎忽略了对 divs 的修改,这些修改以“显示:none”开头。这是符合规范还是 Chrome 中的错误?
屏幕 reader 是否显示实际单词“警报”是屏幕 reader 和浏览器组合的选择。你不能依赖宣布的词。如果您绝对需要宣布它,那么它应该是您的信息的一部分。
alert spec 说:
“如果操作系统允许,用户代理应该通过可访问性触发系统警报事件API”
请注意,“应该”并不意味着“必须”。 “应该”的定义在 rfc2119 中说:
"3. SHOULD 这个词,或者形容词“RECOMMENDED”,意思是那里
在特定情况下可能存在忽略某项的正当理由
特定项目,但必须了解其全部含义,并且
在选择不同的课程之前仔细权衡。"
也就是说,应该表示鼓励但不强制要求。所以循环回来,建议但不是必需的“警报”公告(通过发布警报系统事件)。
因此,如果您的主要问题是如何在所有平台(PC、Mac、移动设备)的所有浏览器上通过所有屏幕 reader 宣布“警报”一词,那么您d 需要直接在您的错误消息中对单词进行编码。 “警报”一词不必在屏幕上可见,但必须注入活动区域。
另请注意,role="alert"
为您提供了隐含的 aria-live="assertive"
和 aria-atomic="true"
,因此您无需指定这些属性。在您的情况下,您正在覆盖隐式 aria-live="assertive"
并专门设置 aria-live="polite"
。这样做应该不会造成任何伤害,但您正在破坏使用警报角色的目的。
屏幕 reader 是一次还是两次宣布实际消息由屏幕 reader 决定。在 Firefox 上,我确实听到了两次宣布的错误消息,一次前面有“警报”,一次没有。在 Chrome 上,我只听到一次,但没有说“警报”。但是在两个浏览器上,消息都公布了,这就是直播区的目的。
您在实际生产代码中提到,Chrome/NVDA 上没有公布任何内容。那会很奇怪。我从来没有遇到过使用 aria-live
而消息没有被公布的情况。我只能评论你发布的示例代码。
正如我在问题的编辑部分中已经提到的,核心问题是我将错误消息添加到 JavaScript 的 div 的初始显示样式属性设置为“ none”。它最初也是空的。
<div id="lblErr" style="display: none;" role="alert" aria-atomic="true" aria-live="polite" tabindex="3"></div>
使用此设置 Google Chrome + NVDA 不会读取动态添加的错误消息。
一旦我删除初始显示样式或将其更改为其他样式Google Chrome + NVDA 开始读取动态添加的错误消息。
我在下面创建了 HTML 演示页面。 In that page a message is added to a div when selecting the "No" radiobutton. div 上面有 aria-tags。有问题的 div 的 ID 为“lblErr”/“lblErr2”。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Screenreader Errormessage Test with Radiobuttons</title>
</head>
<body>
<label id="instructionLbl">
Please select below
</label>
<div>
<div id="firstItemGroup">
<label id="headerTextLbl">
Select no to generate the error message
</label>
<fieldset aria-labelledby="headerTextLbl">
<div id="selectionGroup1">
<table id="radioBtnTable">
<tbody>
<tr>
<td>
<label for="button:conf:1">Yes</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="1" id="button:conf:1" name="button:conf" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr');while(errorDiv.hasChildNodes()){errorDiv.removeChild(errorDiv.lastChild);}">
</input>
</div>
</div>
</td>
<td>
<label for="button:conf:2">No</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="2" id="button:conf:2" name="button:conf" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr');errorDiv.style.display = 'block';var newDiv = document.createElement('div');var spanOne = document.createElement('span');spanOne.classList.add('ui-message-error-icon');var spanTwo = document.createElement('span');spanTwo.classList.add('ui-message-error-detail');var errMsg = document.createTextNode('Very long error message with special red font, details, paragraphs and recovery suggestion is displayed here');spanTwo.appendChild(errMsg);newDiv.appendChild(spanOne);newDiv.appendChild(spanTwo);errorDiv.appendChild(newDiv);">
</input>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div id="lblErr" style="display: none;" role="alert" aria-atomic="true" aria-live="polite" tabindex="3"></div>
</div>
</fieldset>
</div>
<div id="subItemsGroup">
<label id="headerTextLbl2">
Label with headertext
</label>
<fieldset aria-labelledby="headerTextLbl2">
<div id="selectionGroup2">
<label id="instructionLbl2">Select no to generate the error message</label>
<table id="radioBtnTable2">
<tbody>
<tr>
<td>
<label for="button:conf:3">Yes</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="4" id="button:conf:3" name="button:conf:2" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr2');while(errorDiv.hasChildNodes()){errorDiv.removeChild(errorDiv.lastChild);}">
</input>
</div>
</div>
</td>
<td>
<label for="button:conf:4">No</label>
<div class="ui-radiobutton ui-widget">
<div class="ui-helper-hidden-accessible">
<input tabindex="5" id="button:conf:4" name="button:conf:2" type="radio" value="false" onchange="var errorDiv = document.getElementById('lblErr2');errorDiv.style.display = 'block';var newDiv = document.createElement('div');var spanOne = document.createElement('span');spanOne.classList.add('ui-message-error-icon');var spanTwo = document.createElement('span');spanTwo.classList.add('ui-message-error-detail');var errMsg = document.createTextNode('Very long error message with special red font, details, paragraphs and recovery suggestion is displayed here');spanTwo.appendChild(errMsg);newDiv.appendChild(spanOne);newDiv.appendChild(spanTwo);errorDiv.appendChild(newDiv);">
</input>
</div>
</div>
</td>
</tr>
</tbody>
</table>
<div id="lblErr2" style="display: none;" role="alert" aria-atomic="true" aria-live="polite" tabindex="6"></div>
</div>
</fieldset>
</div>
</div>
</body>
</html>
添加错误信息的JavaScript代码。我将它添加到单选按钮的 onChange 中:
var errorDiv = document.getElementById('lblErr');
var newDiv = document.createElement('div');
var spanOne = document.createElement('span');
spanOne.classList.add('ui-message-error-icon');
var spanTwo = document.createElement('span');
spanTwo.classList.add('ui-message-error-detail');
var errMsg = document.createTextNode('Very long error message with special red font, details, paragraphs and recovery suggestion is displayed here');
spanTwo.appendChild(errMsg);
newDiv.appendChild(spanOne);
newDiv.appendChild(spanTwo);
errorDiv.appendChild(newDiv);
这是我们制作的HTML / JS 的提取和简化版本。在生产中,这些选择中有 5 到 6 个一个在另一个下面,它被嵌入到一个更大的 HTML 结构中(有多个父 divs,它们也有导航元素和其他东西)。
此 HTML 在与 Google Chrome 和 NVDA 屏幕 reader 结合使用时存在问题。在生产中选择“否”选项时,错误消息会添加到 HTML,但 NVDA 根本不会读取任何错误消息。 Firefox 中的相同情况导致 NVDA 读取“警报...”。
以下部分已编辑,请参阅下面的编辑内容。
这个简化的演示片段的行为略有不同。此处 Firefox 两次读取错误消息。一次只有消息文本,然后第二次“警报”,然后是消息文本。 Chrome 只读取一次并忽略以“alert”开头的第二条消息。我只希望它在两种浏览器中都显示为“警报...”。
围绕错误消息的 span 和 div 构造在生产环境和我的代码片段中是相同的。
我的问题是:为什么在 Chrome 中添加消息时 NVDA 不读取“警报...”?这是 HTML 或 Chrome 或 NVDA 的问题吗?我可以通过对 HTML 进行非破坏性更改来修复它吗?
编辑: 我现在编辑了 HTML / JS,这样它就不会读取 Chrome 中的任何错误消息,而它仍然读取它在 Firefox 中。发生变化的是 divs lblErr/lblErr2 现在以“显示:none”样式属性开始,即使我在添加错误消息之前删除了它。所以 Chrome / NVDA 似乎忽略了对 divs 的修改,这些修改以“显示:none”开头。这是符合规范还是 Chrome 中的错误?
屏幕 reader 是否显示实际单词“警报”是屏幕 reader 和浏览器组合的选择。你不能依赖宣布的词。如果您绝对需要宣布它,那么它应该是您的信息的一部分。
alert spec 说:
“如果操作系统允许,用户代理应该通过可访问性触发系统警报事件API”
请注意,“应该”并不意味着“必须”。 “应该”的定义在 rfc2119 中说:
"3. SHOULD 这个词,或者形容词“RECOMMENDED”,意思是那里 在特定情况下可能存在忽略某项的正当理由 特定项目,但必须了解其全部含义,并且 在选择不同的课程之前仔细权衡。"
也就是说,应该表示鼓励但不强制要求。所以循环回来,建议但不是必需的“警报”公告(通过发布警报系统事件)。
因此,如果您的主要问题是如何在所有平台(PC、Mac、移动设备)的所有浏览器上通过所有屏幕 reader 宣布“警报”一词,那么您d 需要直接在您的错误消息中对单词进行编码。 “警报”一词不必在屏幕上可见,但必须注入活动区域。
另请注意,role="alert"
为您提供了隐含的 aria-live="assertive"
和 aria-atomic="true"
,因此您无需指定这些属性。在您的情况下,您正在覆盖隐式 aria-live="assertive"
并专门设置 aria-live="polite"
。这样做应该不会造成任何伤害,但您正在破坏使用警报角色的目的。
屏幕 reader 是一次还是两次宣布实际消息由屏幕 reader 决定。在 Firefox 上,我确实听到了两次宣布的错误消息,一次前面有“警报”,一次没有。在 Chrome 上,我只听到一次,但没有说“警报”。但是在两个浏览器上,消息都公布了,这就是直播区的目的。
您在实际生产代码中提到,Chrome/NVDA 上没有公布任何内容。那会很奇怪。我从来没有遇到过使用 aria-live
而消息没有被公布的情况。我只能评论你发布的示例代码。
正如我在问题的编辑部分中已经提到的,核心问题是我将错误消息添加到 JavaScript 的 div 的初始显示样式属性设置为“ none”。它最初也是空的。
<div id="lblErr" style="display: none;" role="alert" aria-atomic="true" aria-live="polite" tabindex="3"></div>
使用此设置 Google Chrome + NVDA 不会读取动态添加的错误消息。
一旦我删除初始显示样式或将其更改为其他样式Google Chrome + NVDA 开始读取动态添加的错误消息。