尽管组件的功能随屏幕尺寸而变化,但如何在组件内保持良好的可访问性?
How can I maintain good accessibility within a component despite its functionality changing with screen size?
我目前正在构建一个由三个无序列表组成的响应式组件,每个列表都有一个关联的标题。代码看起来像这样:
<div>
<section aria-labelledby="heading1">
<h3 id="heading1" data-state="open">Heading 1</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<section aria-labelledby="heading2">
<h3 id="heading2" data-state="open">Heading 2</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<section aria-labelledby="heading3">
<h3 id="heading3" data-state="open">Heading 3</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
</div>
在较大的屏幕上,CSS 将其呈现为三列,而在较小的屏幕上,它变成手风琴,点击标题将切换相邻列表的显示。 open/close 功能由 Javascript 处理,只是在打开和关闭之间切换数据状态。
这一切都很好,但在可访问性方面我有点难过。我想告诉辅助技术标题是按钮(使用 role="button" 或将标题文本包装在按钮元素中),但这只有在显示为手风琴时才是正确的。在 three-column 模式下,标题不应该是按钮,只是标题。
如有任何帮助,我们将不胜感激!
所以 DOM 保持不变?没有在响应式视图中添加额外的 HTML 元素?
如果是这样,那就有点棘手了,但您可以使用 Accordion Design Pattern,然后在全屏模式下调整元素的属性。
手风琴包括:
- 手风琴元素 – collection 面板包含在外面板(通常是列表)
- Accordion header – 可扩展和可折叠的手风琴面板的标记区域
- 手风琴面板 – 包含特定于每个 header
的内容的区域(容器)
每个手风琴的标题 header 包含在 <button>
或带有 role="button"
的元素中。
每个手风琴 header 按钮都包装在一个 <hX>
元素中,其级别适合页面的信息架构。按钮元素是标题元素中的唯一元素。
如果与手风琴 header 关联的手风琴面板可见,则 header 按钮元素 aria-expanded
设置为 "true" .如果面板不可见,aria-expanded
设置为 "false"。面板本身应适当设置 aria-hidden
或使用 CSS (display:none
) 隐藏。
手风琴面板有 role="region"
和 aria-labelledby
,其值引用控制面板显示的按钮。
这与您发布的代码非常接近。您的列表 (<section>
) 有一个容器,其中有一个 default role of region
,您通过将其指向标题来标记该部分。
因此,一旦您有了手风琴代码,当显示只是一个简单的三列列表时,您就可以决定不需要该结构的哪些部分。
<!-- main accordion container -->
<div>
<h2>
<button aria-expanded="false" id="accordion1id">first accordion section</button>
</h2>
<section aria-labelledby="accordion1id">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<h2>
<button aria-expanded="false" id="accordion2id">second accordion section</button>
</h2>
<section aria-labelledby="accordion2id">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
</div>
这非常接近您的原始代码。当您只需要列表结构(桌面视图)时,您应该能够将 role="presentation"
添加到所有 <button>
元素,这将删除元素的“按钮性”并将它们基本上变成纯文本所以所有您剩下的是带有 child 文本的标题。屏幕 reader 只会知道有一个标题后跟一个带有嵌入列表的部分。
您也应该从按钮中删除 aria-expanded
,因为该属性只对按钮有效,对纯文本元素无效。
如果需要,您还可以删除 <section>
上的 aria-labelledby
,这会删除这些元素的 landmark
角色,这样它们就会被屏幕忽略 reader也是。代码看起来像这样:
<!-- main accordion container -->
<div>
<h2>
<button role="presentation" id="accordion1id">first accordion section</button>
</h2>
<section>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<h2>
<button role="presentation" id="accordion2id">second accordion section</button>
</h2>
<section>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
</div>
屏幕 reader 实际看到的是:
<div>
<h2>
first accordion section
</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<h2>
second accordion section
</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
更新
谢谢,@Robin,你是对的。 ARIA 属性只是 提示 辅助技术,不会影响 行为 因此将 role="presentation"
添加到 <button>
,虽然它确实使按钮不再宣布为按钮,但这不会阻止用户跳转到它或单击它,因此您需要在按钮上 tabindex="-1"
以防止跳转,并且您需要将按钮上的事件处理为 NO-OPs。您可能还需要应用 CSS,这样按钮看起来也不像按钮。这一切都是可行的,但有时更容易换入和换出不同的组件。
我目前正在构建一个由三个无序列表组成的响应式组件,每个列表都有一个关联的标题。代码看起来像这样:
<div>
<section aria-labelledby="heading1">
<h3 id="heading1" data-state="open">Heading 1</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<section aria-labelledby="heading2">
<h3 id="heading2" data-state="open">Heading 2</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<section aria-labelledby="heading3">
<h3 id="heading3" data-state="open">Heading 3</h3>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
</div>
在较大的屏幕上,CSS 将其呈现为三列,而在较小的屏幕上,它变成手风琴,点击标题将切换相邻列表的显示。 open/close 功能由 Javascript 处理,只是在打开和关闭之间切换数据状态。
这一切都很好,但在可访问性方面我有点难过。我想告诉辅助技术标题是按钮(使用 role="button" 或将标题文本包装在按钮元素中),但这只有在显示为手风琴时才是正确的。在 three-column 模式下,标题不应该是按钮,只是标题。
如有任何帮助,我们将不胜感激!
所以 DOM 保持不变?没有在响应式视图中添加额外的 HTML 元素?
如果是这样,那就有点棘手了,但您可以使用 Accordion Design Pattern,然后在全屏模式下调整元素的属性。
手风琴包括:
- 手风琴元素 – collection 面板包含在外面板(通常是列表)
- Accordion header – 可扩展和可折叠的手风琴面板的标记区域
- 手风琴面板 – 包含特定于每个 header 的内容的区域(容器)
每个手风琴的标题 header 包含在 <button>
或带有 role="button"
的元素中。
每个手风琴 header 按钮都包装在一个 <hX>
元素中,其级别适合页面的信息架构。按钮元素是标题元素中的唯一元素。
如果与手风琴 header 关联的手风琴面板可见,则 header 按钮元素 aria-expanded
设置为 "true" .如果面板不可见,aria-expanded
设置为 "false"。面板本身应适当设置 aria-hidden
或使用 CSS (display:none
) 隐藏。
手风琴面板有 role="region"
和 aria-labelledby
,其值引用控制面板显示的按钮。
这与您发布的代码非常接近。您的列表 (<section>
) 有一个容器,其中有一个 default role of region
,您通过将其指向标题来标记该部分。
因此,一旦您有了手风琴代码,当显示只是一个简单的三列列表时,您就可以决定不需要该结构的哪些部分。
<!-- main accordion container -->
<div>
<h2>
<button aria-expanded="false" id="accordion1id">first accordion section</button>
</h2>
<section aria-labelledby="accordion1id">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<h2>
<button aria-expanded="false" id="accordion2id">second accordion section</button>
</h2>
<section aria-labelledby="accordion2id">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
</div>
这非常接近您的原始代码。当您只需要列表结构(桌面视图)时,您应该能够将 role="presentation"
添加到所有 <button>
元素,这将删除元素的“按钮性”并将它们基本上变成纯文本所以所有您剩下的是带有 child 文本的标题。屏幕 reader 只会知道有一个标题后跟一个带有嵌入列表的部分。
您也应该从按钮中删除 aria-expanded
,因为该属性只对按钮有效,对纯文本元素无效。
如果需要,您还可以删除 <section>
上的 aria-labelledby
,这会删除这些元素的 landmark
角色,这样它们就会被屏幕忽略 reader也是。代码看起来像这样:
<!-- main accordion container -->
<div>
<h2>
<button role="presentation" id="accordion1id">first accordion section</button>
</h2>
<section>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
<h2>
<button role="presentation" id="accordion2id">second accordion section</button>
</h2>
<section>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</section>
</div>
屏幕 reader 实际看到的是:
<div>
<h2>
first accordion section
</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<h2>
second accordion section
</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</div>
更新
谢谢,@Robin,你是对的。 ARIA 属性只是 提示 辅助技术,不会影响 行为 因此将 role="presentation"
添加到 <button>
,虽然它确实使按钮不再宣布为按钮,但这不会阻止用户跳转到它或单击它,因此您需要在按钮上 tabindex="-1"
以防止跳转,并且您需要将按钮上的事件处理为 NO-OPs。您可能还需要应用 CSS,这样按钮看起来也不像按钮。这一切都是可行的,但有时更容易换入和换出不同的组件。