辅助功能:在小型设备上以模态显示内容,在大型设备上以内联方式显示内容
Accessibility: show content in modal on small devices, show content inline on large devices
我需要在小型设备的 modal/fullscreen 面板中显示某些内容,由按钮触发。在大型设备上,相同的内容始终显示,然后隐藏触发器。
您如何处理此问题的可访问性?
目前,我有这个设置
<button type="button" aria-expanded="false" aria-controls="filter-panel">Filter</button>
<div class="o-panel" id="filter-panel">Form</div>
最初,o-panel
通过 CSS 在小型设备上隐藏(在针对小型设备的媒体查询中)。当触发器被触发时,我将 aria-expanded
设置为 true,并向面板本身添加一个 active
class,它通过 CSS 显示全屏 o-panel
。在大型设备上,我隐藏按钮并始终通过 CSS(在针对大型设备的媒体查询中)内联显示来自 o-panel
的内容,它位于 HTML 中。
这对可访问性有意义吗?我的面板没有显示 role="dialog"
,因为在大型设备上它只是内容,而不是对话框。我的按钮在这些大设备上隐藏是不是问题?
我真的不知道我应该在这里做什么。如果我将 role="dialog"
添加到我的 o-panel,我是否应该为大型设备删除这个 属性,它实际上不是模态?
或者我是否应该将 o-panel
中的 copy/move 内容移动到 div 和 role="dialog"
中,以防触发器被触发?我只是不想要相同内容的两份副本。
确保在 <head>
标签中包含 <meta name="viewport" content="width=device-width, initial-scale=1.0">
。
然后根据您的风格,您可以使用
@media only screen and (max-width:620px) {
/* For mobile phones: */
}
您可以在此处了解有关 @media
规则的更多信息:W3Schools Media Rule。
如果还有什么问题一定要问!
辅助功能属性只是 aria-expanded="false" aria-controls="filter-panel" 不要更改它。
您的 class 和 ID 名称对可访问性没有任何影响。
如果您只想在大型设备上默认显示内容,并显示仅在智能手机设备上显示的号召性用语,您可以使用 javascript 和 media-query 来实现。
在大型设备上,您需要做几件事。
正确隐藏按钮
首先确保按钮是 display:none
,而不是 visibility:hidden
或其他任何按钮,否则它仍会显示在辅助功能树中。
主要(<main>
)问题
模态框应该出现在 <main>
之外。
这样您就可以在模态处于活动状态时将 aria-hidden="true"
添加到 <main>
元素,以阻止人们在屏幕 reader 上导航到模态之外。 (屏幕 reader 用户使用标题、链接等来导航页面,因此您不能只拦截 tab 键。)
现在我的理念是移动优先,所以我会说您的标记应该是移动优先的。这意味着如前所述,将模式放在 <main>
之外。
这显然会在桌面上造成很大的问题。您现在将内容放在了不应该放在的地方。
因此,您实际上只有两个选择。
选项 1
使用 JavaScript 在预定义的占位符 <div>
中重新定位模态内容。
所以你保持你的移动优先设计,然后使用 JavaScript 找到你的模态的 innerHTML
并将它移动到你的支架内的 body 中。然后删除模态本身只是为了确定。
当你这样做的时候,我也会删除按钮,以防万一有人将屏幕大小调整为移动视图,我们不希望按钮无处可去。
或者不要删除第二个内容,这样人们就可以调整浏览器的大小,这意味着一些额外的 DOM 节点(只要您的模态内容不超过 100 个 DOM 元素我会说这样做。)
如果您决定保留模式,请确保它是 也是 display: none
出于与按钮相同的原因,我们不希望人们意外访问它。
选项 2
重复内容。
我知道,我知道,重复的内容只是,呃。
但有时你只需要忍受它,如果它是最好的。
从一开始就将内容复制到 div 中,您确实可以获得一些优势。
优势
- 如果用户调整屏幕大小,您可以使用 CSS 在视图之间切换。
- 不需要 JavaScript,如果您的站点没有 JS 或 当 您的 JavaScript 失败时,这非常有用。
- 虽然它增加了页面重量,但它可能会提高整体性能,但第一个选项可能会改变布局,从而导致高 Cumulative Layout Shift is quite high (although avoidable). With Google putting so much emphasis on Web Vitals 我现在会开始考虑它们。此外,如果您的模态仅包含几个元素,您可能会发现您写的 JavaScript 几乎与 HTML 一样多。
缺点
- 由于重复 HTML.
,您的页面重量会增加
- 您可能需要调整脚本等以解决第二个重复项目(尽管这应该是次要的)。
这仍然是我的偏好,Keep It Simple!这更强大
选项 3(未来)
Client Hints 是解决此问题的一种方法,将响应式设计转变为移动与桌面和响应式的混合体。
当客户端提示有足够的市场份额时,您可以简单地使用 header 来决定从初始请求发送哪个版本的页面。
如果您愿意让 25% 的用户在桌面上看到您的信息的移动版本,那么您今天就可以实现这一点,具体取决于信息的重要性。
其他注意事项
还有一些需要考虑的地方你没有提到所以我想补充一下以供参考。
我已经提到在模态框处于活动状态时将 aria-hidden
添加到模态框之外的所有元素。
为了将来验证您的应用程序,请使用 inert
on items outside of the modal. Support isn't great (none existent!),但每一个细节都会有所帮助,并且很可能会得到实施!
如果你愿意,你可以对其进行 polyfill,但我认为它还没有超出规范草案的范围,所以我们只是按原样使用它。
同时将 aria-modal="true"
添加到您的模态框。
我稍微介绍了很多这些要点more detail in this answer if you want a bit more info.
我需要在小型设备的 modal/fullscreen 面板中显示某些内容,由按钮触发。在大型设备上,相同的内容始终显示,然后隐藏触发器。
您如何处理此问题的可访问性?
目前,我有这个设置
<button type="button" aria-expanded="false" aria-controls="filter-panel">Filter</button>
<div class="o-panel" id="filter-panel">Form</div>
最初,o-panel
通过 CSS 在小型设备上隐藏(在针对小型设备的媒体查询中)。当触发器被触发时,我将 aria-expanded
设置为 true,并向面板本身添加一个 active
class,它通过 CSS 显示全屏 o-panel
。在大型设备上,我隐藏按钮并始终通过 CSS(在针对大型设备的媒体查询中)内联显示来自 o-panel
的内容,它位于 HTML 中。
这对可访问性有意义吗?我的面板没有显示 role="dialog"
,因为在大型设备上它只是内容,而不是对话框。我的按钮在这些大设备上隐藏是不是问题?
我真的不知道我应该在这里做什么。如果我将 role="dialog"
添加到我的 o-panel,我是否应该为大型设备删除这个 属性,它实际上不是模态?
或者我是否应该将 o-panel
中的 copy/move 内容移动到 div 和 role="dialog"
中,以防触发器被触发?我只是不想要相同内容的两份副本。
确保在 <head>
标签中包含 <meta name="viewport" content="width=device-width, initial-scale=1.0">
。
然后根据您的风格,您可以使用
@media only screen and (max-width:620px) {
/* For mobile phones: */
}
@media
规则的更多信息:W3Schools Media Rule。
如果还有什么问题一定要问!
辅助功能属性只是 aria-expanded="false" aria-controls="filter-panel" 不要更改它。
您的 class 和 ID 名称对可访问性没有任何影响。
如果您只想在大型设备上默认显示内容,并显示仅在智能手机设备上显示的号召性用语,您可以使用 javascript 和 media-query 来实现。
在大型设备上,您需要做几件事。
正确隐藏按钮
首先确保按钮是 display:none
,而不是 visibility:hidden
或其他任何按钮,否则它仍会显示在辅助功能树中。
主要(<main>
)问题
模态框应该出现在 <main>
之外。
这样您就可以在模态处于活动状态时将 aria-hidden="true"
添加到 <main>
元素,以阻止人们在屏幕 reader 上导航到模态之外。 (屏幕 reader 用户使用标题、链接等来导航页面,因此您不能只拦截 tab 键。)
现在我的理念是移动优先,所以我会说您的标记应该是移动优先的。这意味着如前所述,将模式放在 <main>
之外。
这显然会在桌面上造成很大的问题。您现在将内容放在了不应该放在的地方。
因此,您实际上只有两个选择。
选项 1
使用 JavaScript 在预定义的占位符 <div>
中重新定位模态内容。
所以你保持你的移动优先设计,然后使用 JavaScript 找到你的模态的 innerHTML
并将它移动到你的支架内的 body 中。然后删除模态本身只是为了确定。
当你这样做的时候,我也会删除按钮,以防万一有人将屏幕大小调整为移动视图,我们不希望按钮无处可去。
或者不要删除第二个内容,这样人们就可以调整浏览器的大小,这意味着一些额外的 DOM 节点(只要您的模态内容不超过 100 个 DOM 元素我会说这样做。)
如果您决定保留模式,请确保它是 也是 display: none
出于与按钮相同的原因,我们不希望人们意外访问它。
选项 2
重复内容。
我知道,我知道,重复的内容只是,呃。
但有时你只需要忍受它,如果它是最好的。
从一开始就将内容复制到 div 中,您确实可以获得一些优势。
优势
- 如果用户调整屏幕大小,您可以使用 CSS 在视图之间切换。
- 不需要 JavaScript,如果您的站点没有 JS 或 当 您的 JavaScript 失败时,这非常有用。
- 虽然它增加了页面重量,但它可能会提高整体性能,但第一个选项可能会改变布局,从而导致高 Cumulative Layout Shift is quite high (although avoidable). With Google putting so much emphasis on Web Vitals 我现在会开始考虑它们。此外,如果您的模态仅包含几个元素,您可能会发现您写的 JavaScript 几乎与 HTML 一样多。
缺点
- 由于重复 HTML. ,您的页面重量会增加
- 您可能需要调整脚本等以解决第二个重复项目(尽管这应该是次要的)。
这仍然是我的偏好,Keep It Simple!这更强大
选项 3(未来)
Client Hints 是解决此问题的一种方法,将响应式设计转变为移动与桌面和响应式的混合体。
当客户端提示有足够的市场份额时,您可以简单地使用 header 来决定从初始请求发送哪个版本的页面。
如果您愿意让 25% 的用户在桌面上看到您的信息的移动版本,那么您今天就可以实现这一点,具体取决于信息的重要性。
其他注意事项
还有一些需要考虑的地方你没有提到所以我想补充一下以供参考。
我已经提到在模态框处于活动状态时将 aria-hidden
添加到模态框之外的所有元素。
为了将来验证您的应用程序,请使用 inert
on items outside of the modal. Support isn't great (none existent!),但每一个细节都会有所帮助,并且很可能会得到实施!
如果你愿意,你可以对其进行 polyfill,但我认为它还没有超出规范草案的范围,所以我们只是按原样使用它。
同时将 aria-modal="true"
添加到您的模态框。
我稍微介绍了很多这些要点more detail in this answer if you want a bit more info.