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”开头的第二条消息。我只希望它在两种浏览器中都显示为“警报...”。

围绕错误消息的 spandiv 构造在生产环境和我的代码片段中是相同的。

我的问题是:为什么在 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 开始读取动态添加的错误消息。