当aria-expanded为true时,如何让屏幕阅读器正确说出“按钮已扩展”

时间:2019-05-31 16:52:01

标签: jquery accessibility accordion wai-aria screen-readers

我正在努力通过aria扩展标签等aria标签来访问我们的手风琴。单击手风琴触发器标题或按下键盘上的“返回”按钮后,我正确地获得了aria扩展更改的值。出于某种原因,尽管我正在测试的ChromeVox最初只会说“按钮合拢”,而单击后值改变则不说“按钮合拢”。

我查看了https://www.w3.org/TR/wai-aria-practices/examples/accordion/accordion.html等其他网站上的示例,ChromeVox在此处正确读取了aria扩展的两种状态,因此我认为这与代码结构有关,从而阻止了ChromeVox的发布“展开”状态。

以下是一个手风琴部分的示例:


    <div class="accordion-section">

        <button tabIndex="0" id="rules_list" class="accordion" aria-expanded="false" aria-controls="sectRules">
            <span class="title">Rules</span>
        </button>

        <div class="content" role="region" id="sectRules" aria-labledby="rules_list">

            <h4>What rules must all visitors follow?</h4>

            <ul class="list">
            <li style="list-style-type:disc; border-top:0px; margin-bottom:0px; padding-bottom:0px; padding-top:10px; overflow:visible;">rule 1</li>
            <li style="list-style-type:disc; border-top:0px; margin-bottom:0px; padding-bottom:0px; padding-top:10px; overflow:visible;">rule 2</li>
            <li style="list-style-type:disc; border-top:0px; margin-bottom:0px; padding-bottom:0px; padding-top:10px; overflow:visible;">rule 3 etc..</li>
            </ul>

        </div>

    </div>
    ```
    The relevant js is:

    ```
    /* Generic Accordion */
    $('.accordion .title').click(function() {
       $(this).parent().parent().children('.content').toggle();
       $(this).toggleClass('open');

       $(this).hasClass("open") ? $(this).parent().attr("aria-expanded", "true") : $(this).parent().attr("aria-expanded", "false");

    });

    /* Adding support for keyboard */
        $('.accordion').on('keydown', function(e) {
          if (/^(13|32)$/.test(e.which)) {
            e.preventDefault();
            $(this).find('.title').click();
          }
        });


    ```



    The relevant CSS is :
    ```
    .accordion + .content{
      display: none;
      margin-top: 10px;
      padding: 10px;}

    .accordion + .content.open{
      display: block;
      background-color: white;}
    ```

I'm at a loss, any help would be much appreciated.

3 个答案:

答案 0 :(得分:1)

您将单击处理程序放在跨度上,而不是按钮上?由于aria-expanded位于按钮上,因此,这似乎不正确,可能是问题的原因。

配音可能正在事件目标aria-expanded而非按钮上寻找span。当然找不到。

这也许可以解释为什么当按钮获得焦点时而不是单击时宣布状态。

因此,请检查是否将单击添加到按钮(而不是跨度)是否可以提供所需的结果。而且,如果执行此操作,则可以跳过parent()中的toggle()步骤之一。

此外,我将在aria-expanded上设置.content并使其与按钮上的aria-expanded属性保持同步。

答案 1 :(得分:1)

我第二次brennanyoung对您使用span元素的方式以及为什么它可能是您的代码无法按预期工作的原因的看法。

在我看来,您确实应该考虑使用button元素来切换内容,因为这样可以避免一些额外的工作,例如:

  • 确保span覆盖了整个按钮,以防止单击按钮而不会导致任何结果(说出来听起来很奇怪),
  • 集中处理span
  • 确保span的行为就像button(单击,按下和其他button相关事件)一样。

此外,以编程方式触发代码中的click事件也暗示着可以轻松完成一些事情。

hidden + aria-labelledby

我倾向于通过在要切换的内容上使用hidden attribute和在按钮上进行切换来使用aria-expanded来使其尽可能简单。

如果需要,Heydon Pickering的

Collapsible Sections of the "Inclusive components book" 是一本很好的读物……可折叠的部分。实际上,整本书都很棒,如果您还没有的话,也不会浪费时间。

hidden属性已由屏幕阅读器正确处理,并将在视觉上和可访问性树中隐藏该元素。您几乎可以在任何最新的Web浏览器(https://caniuse.com/#search=hidden)上使用它,这使其成为避免使用类和CSS display属性的好选择。

如果您要在内容上使用aria-labelledby(顺便说一下,两个“ L”表示您的代码中缺少一个)(并且应该将其声明为一个区域),请使用将button文本作为标签可以正常工作。

但是,如果您打算使用描述操作的文本(例如,根据状态显示“显示规则”或“隐藏规则”),那么这将不再适用,您将不得不使用另一个元素作为此地标的标签。您的代码中的h4元素似乎可以完成工作,而给它一个id可以让屏幕阅读器更轻松地识别区域。

示例

我随意重写了您提供的仅使用纯JS的示例,并做了一些小的调整。它是可测试的here

<div class="accordion-section" id="accordion-1">

    <button id="rules-list" class="rules-toggle" aria-expanded="true" aria-controls="sect-rules">
        <span>Rules</span>
    </button>

    <section role="region" class="content" id="sect-rules" aria-labelledby="rules-list-title">

        <h4 id="rules-list-title">What rules must all visitors follow?</h4>

        <ul class="list">
            <li>rule 1</li>
            <li>rule 2</li>
            <li>rule 3</li>
        </ul>

    </section>

</div>
const myButton = document.querySelector('#accordion-1 .rules-toggle');
myButton.addEventListener('click', toggleRules);

function toggleRules(evt) {
  const button = evt.currentTarget;
  const accordionSection = button.parentElement;
  const content = accordionSection.querySelector('.content');

  if ('hidden' in content.attributes) {
    content.removeAttribute('hidden');
    button.setAttribute('aria-expanded', true);
  } else {
    content.setAttribute('hidden', true);
    button.setAttribute('aria-expanded', false);
  }
}
.rules-toggle + .content {
  margin-top: 10px;
  padding: 10px;
  background-color: white;
}

.list li {
  list-style-type: disc;
  border-top: 0;
  margin-bottom: 0;
  padding-bottom: 0;
  padding-top: 10px;
  overflow: visible;
}

答案 2 :(得分:0)

这是我的最终解决方案,适用于多个部分:

````
   let elementsArray = document.querySelectorAll(".rules-toggle");

   elementsArray.forEach(function(elem) {
      elem.addEventListener("click", function (evt) {
        const button = evt.currentTarget;
        const accordionSection = button.parentElement;
        const content = accordionSection.querySelector('.content');

       if ('hidden' in content.attributes) {
         content.removeAttribute('hidden');
         button.setAttribute('aria-expanded', true);
       } else {
        content.setAttribute('hidden', true);
        button.setAttribute('aria-expanded', false);
       }
     });
});