使屏幕阅读器可以访问搜索表单

making a searchform accesible for screenreaders

我正在使用复选框来显示和隐藏搜索表单。当标签被点击时,复选框被选中。 所以我认为我已经解决了所有问题,一些奇特的角色和 aria 属性在这里和那里使它在可访问性方面表现得很好。

CSS 正在施展魔法:

#cb-search-form:checked + .page-search {
    display: block;
}

这是html:

<div class="header-icons">
    <label for="cb-search-form" class="btn js-has-popup" id="searchFormLbl" role="button" tabindex="0" aria-haspopup="true" aria-expanded="false">
        <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16" class="bi bi-search" width="1em" height="1em"><path d="M11.742 10.344a6.5 6.5 0 10-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 001.415-1.414l-3.85-3.85a1.007 1.007 0 00-.115-.1zM12 6.5a5.5 5.5 0 11-11 0 5.5 5.5 0 0111 0z"></path></svg>
        <span class="sr-only">open search form</span>
    </label>
</div>

<input type="checkbox" id="cb-search-form">

<div class="page-search js-focus" aria-labelledby="searchFormLbl" aria-hidden="true">
    <label for="cb-search-form" class="btn close js-has-popup-closer" aria-label="Close">
        <span aria-hidden="true">&times;</span>
    </label>

    <form action="searchpage" class="form js-page-search" id="form-search" method="POST" novalidate itemprop="potentialAction" itemscope itemtype="http://schema.org/SearchAction">
        <meta itemprop="target" content="searchpage?q={q}">
        <!-- the inputs fields and stuff here -->
    </form>
</div>

标签似乎没有有效的互动。我猜作为按钮的角色并不是真的有效。当我在聚焦时按 Enter 时,它上面的 tabindex 根本不合作。该复选框未被选中。 我认为这永远不会“修复”:https://bugs.chromium.org/p/chromium/issues/detail?id=122652

这个屏幕阅读器友好吗,我什至不确定我是否应该“修复”这个问题?

我认为这是在没有 javascript 的情况下这样做的好方法。

为了清楚起见,我假设这是 JS 失败时的后备/它被关闭的边缘情况,而不是无 JS 的解决方案。

这种区别很重要,就好像这是一个“无 JS”解决方案,您的所有角色信息都需要删除。

使用复选框作为无 JS 回退的最佳实践

你应该做的是从一个复选框和 CSS 解决方案(无需 JS 即可工作)开始,然后通过 渐进增强 ,添加 role="button" 与 JavaScript 而不是一开始就把它放在那里。

从那时起,您只需将其视为 <button> 元素即可。

但是, role 需要移动到 <input type="checkbox" 而不是 <label>,连同所有相关的 WAI-ARIA! (请参阅下面的“关注复选框而不是标签”h2)

此外,“Enter”不起作用的原因是因为添加 role 只会改变 语义 的含义,它不会添加功能。复选框仅适用于 Space.

因此,您需要通过 JavaScript 和 element.addEventListener('keydown'... 添加此功能,并监听“Enter”键(键 13)以更改选中状态,使其现在的行为类似于按钮.

关注复选框而不是标签

最后,当使用任何复选框时 - 像这样标记“hacks”应该获得焦点的项目应该是复选框本身而不是标签。

某些屏幕 reader 和浏览器组合不会宣布选中状态,例如,如果您聚焦 <label>

另一个要考虑的是语音导航,我不知道像“龙自然说话”这样的东西会如何表现。但是我不知道我不能以任何有意义的方式发表评论,除了有根据的猜测,由于使用 Dragon 的经验在变通方法中表现不佳,这不会非常可靠。

我的意思是,Dragon even has problems with implicit labels 这表明由于辅助技术的分散支持,有时您必须多加小心。

改变你的 CSS / HTML

因此,您使用 隐藏复选框,但将其放置在这样一种方式中,即当它获得焦点时,您可以使用 input[type="checkbox"]:focus ~ label{/*your focus indicators*/} 之类的方式将焦点指示器添加到标签。您需要移动 <div class="header-icons" 中的复选框和 .page-search 才能使用兄弟选择器。

我也鼓励您使用我链接的 ,因为 bootstrap sr-only class 有一些缺陷。

希望这是有道理的,有任何问题都可以问。

快速演示

我没有整理你的任何role信息等在下面的演示中,我所做的只是删除标签上的tabindex="0"

该演示纯粹是为了展示如何使复选框获得焦点并且仍然将焦点指示器放在标签上。

.visually-hidden { 
    border: 0;
    padding: 0;
    margin: 0;
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
    clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
    clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
    white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}

#searchFormLbl{
   display: inline-block;
   padding: 5px;
}

input[type="checkbox"]:focus ~ label{
/*your focus indicators*/
outline: 0;
border: 0;
outline: 4px solid #333;
outline-offset: 4px;
}


.page-search{
    margin-top: 20px;
    display: none;
}

#cb-search-form:checked ~ .page-search {
    display: block!important;
}
<div class="header-icons">
    <input type="checkbox" id="cb-search-form" class="visually-hidden">
    <label for="cb-search-form" class="btn js-has-popup" id="searchFormLbl" role="button" aria-haspopup="true" aria-expanded="false">
        <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16" class="bi bi-search" width="1em" height="1em"><path d="M11.742 10.344a6.5 6.5 0 10-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 001.415-1.414l-3.85-3.85a1.007 1.007 0 00-.115-.1zM12 6.5a5.5 5.5 0 11-11 0 5.5 5.5 0 0111 0z"></path></svg>
        <span class="sr-only">open search form</span>
    </label>
<div class="page-search js-focus" aria-labelledby="searchFormLbl">
    I am open
</div>
</div>