将焦点添加到弹出 /模态时单击以获取选项卡 /可访问性-JavaScript
我有一个元素“单击”上出现的弹出/覆盖层。因为弹出窗口背后有很多HTML内容,所以POP上的按钮/输入元素自然不会具有焦点/Tabindex行为。出于可访问性的原因,我想要它,以便当此弹出我们显示模式中的元素时具有焦点/选项卡索引优先级,而不是其背后的主要内容。
在下面的简单演示中 - 单击“单击我”按钮后,当您使用“选项卡键”时,浏览器仍在覆盖层后面的输入元素中标签。
在显示出显示时如何给出覆盖行为的任何建议将不胜感激。
在模态上创建focus
事件似乎不起作用?
codepen: https://codepen.io/anna_papaul/pen/anna_paul/pen/pen/pen/pen/yyywzbzbzbzbz
/strong>
我几乎可以得到乔治·查普曼(George Chapman)的编码词答案,但是当您按住Enter键时,它会在覆盖层出现而不出现之间来回闪烁,并且似乎在Safari中不起作用吗?
let clickMe = document.querySelector('#click-me'),
modal = document.querySelector('.modal'),
closeButton = document.querySelector('.close')
clickMe.addEventListener('click', () => {
modal.style.display = 'flex';
// modal.focus();
})
closeButton.addEventListener('click', () => {
modal.style.display = 'none';
})
body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
input, button {
margin: 1rem;
padding: .5rem;
}
.click-me {
display: block;
}
.modal {
display: none;
flex-direction: column;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
background: grey;
position: absolute;
}
form {
display: flex;
}
<button id="click-me">Click Me</button>
<form action="">
<input type="text" placeholder="An Input">
<input type="text" placeholder="An Input">
<input type="text" placeholder="An Input">
<input type="text" placeholder="An Input">
</form>
<div class="modal">
<button class="close">Close x</button>
<button>More Buttons</button>
<button>More Buttons</button>
</div>
I have a pop-up/overlay that appears on 'click' of an element. Because there is plenty of HTML content behind the pop-up the buttons/input elements on the pop don't naturally have focus/tabindex behaviour. For accessibility reasons I would like it so that when this pop us shows the elements inside the modal have focus/tab index priority not the main content behind it.
In the simple demonstration below - after you click the 'click-me' button, when you use the tab key the browsers still tabs through the input elements behind the overlay.
Any suggestions on how to give the overlay the tab behaviour when it shows would be greatly appreciated.
Creating a focus
event on the modal doesn't seem to work?
Codepen: https://codepen.io/anna_paul/pen/eYywZBz
EDIT
I can almost get George Chapman's Codepen answer to work, but when you hold the enter key down it flashes back and forth between the overlay appearing and not appearing, and it doesn't seem to work in Safari?
let clickMe = document.querySelector('#click-me'),
modal = document.querySelector('.modal'),
closeButton = document.querySelector('.close')
clickMe.addEventListener('click', () => {
modal.style.display = 'flex';
// modal.focus();
})
closeButton.addEventListener('click', () => {
modal.style.display = 'none';
})
body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
input, button {
margin: 1rem;
padding: .5rem;
}
.click-me {
display: block;
}
.modal {
display: none;
flex-direction: column;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
background: grey;
position: absolute;
}
form {
display: flex;
}
<button id="click-me">Click Me</button>
<form action="">
<input type="text" placeholder="An Input">
<input type="text" placeholder="An Input">
<input type="text" placeholder="An Input">
<input type="text" placeholder="An Input">
</form>
<div class="modal">
<button class="close">Close x</button>
<button>More Buttons</button>
<button>More Buttons</button>
</div>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在使模态对话框中访问时,有几件事要考虑,这些内容不仅仅是将焦点放在模态或模态内提取选项卡顺序。您还必须考虑屏幕读取器,如果使用
aria-hidded =“ true”
,那么您仍然需要感知基础页面元素,然后您也需要取消隐藏将模态关闭并恢复基础页面时的那些元素。因此,总而言之,您需要做的是:
您还需要确保模态对话框具有ARIA
roun =“ Dialog”
属性,以便屏幕读取器宣布焦点已移至对话框,理想情况下,您应该使用aria--标记为
和/或aria-descred
属性为您的模态提供可访问的名称和/或说明。这是一个很大的列表,但这通常是针对可访问的模态对话框的建议。请参阅 wai-aria模式对话示例
我已经为您的模态写了一个解决方案,部分基于 hidde De Vries的原始代码用于在模态对话框中限制选项卡顺序。
trapfocusinmodal
函数函数列出了所有聚焦元素的节点列表,并添加了 tab> tab 和 shift> shift ++ tab 确保焦点的密钥不会超越模式中的焦点元素。密钥侦听器还绑定到逃生键以关闭模态。OpenModal
函数显示模式对话框,隐藏了基本的页面元素,将类名称放在元素上,该元素在打开模式之前上次保持焦点,并将焦点设置为模式中的第一个焦点元素。cockemotal
函数关闭模式,未隐藏基础页面,并恢复在打开模式之前上次保持焦点的元素。domisReady
函数等待DOM准备就绪,然后绑定 Enter 键,然后鼠标单击事件到opentmodal
和cockemodal < /代码>功能。
codepen: https://codepen.io/gnchapman/pen/pen/pen/pen/jjjmqyop
There are a few things to consider when making your modal dialog accessible that go beyond just setting focus to your modal or retricting tab order within the modal. You also have to consider that screen readers can still perceive the underlying page elements if they're not hidden from the screen reader using
aria-hidden="true"
, and then you also need to un-hide those elements when the modal is closed and the underlying page is restored.So, to summarise, what you need to do is:
You also need to ensure that your modal dialog has the ARIA
role="dialog"
attribute so that screen readers will announce that focus has moved to a dialog, and ideally you should use thearia-labelledby
and/oraria-describedby
attributes to provide an accessible name and/or description to your modal.That's quite a list, but it's what is generally recommended for accessible modal dialogs. See the WAI-ARIA Modal Dialog Example.
I've written a solution for your modal, partially based on Hidde de Vries's original code for restricting tab order inside a modal dialog.
The
trapFocusInModal
function makes a node list of all focusable elements and adds a key listener for Tab and Shift+Tab keys to ensure focus doesn't move beyond the focusable elements in the modal. The key listener also binds to the Escape key to close the modal.The
openModal
function displays the modal dialog, hides the underlying page elements, places a class name on the element that last held focus before the modal was opened and sets focus to the first focusable element in the modal.The
closeModal
function closes the modal, un-hides the underlying page, and restores focus the element that last held focus before the modal was opened.The
domIsReady
function waits for the DOM to be ready and then binds the Enter key and mouse click events to theopenModal
andcloseModal
functions.Codepen: https://codepen.io/gnchapman/pen/JjMQyoP
出现之后,您必须立即将焦点添加到弹出窗口中时,当您与
collectbutton.focus()
同时进行时,仅此操作,这就是为什么我使用settimeTimeout( )=&gt;
( 当按下箭头键时,它变得可见,因此我使其可见造型:
整个代码:
更新:焦点仅在模态内跳跃:
You have to add focus to the pop-up right after this appears, when you do it simultaneously with
closeButton.focus()
only it won't work that's why I'm usingsetTimeout(() => closeButton.focus(), 1)
, this will added it focus after a1
millisecond.At first, focus on a button isn't visible, it become visible when arrow keys are pressed, so I make it visible styling it:
The whole code:
UPDATE: The focus jumps only within the modal:
我尝试最简单的解决方案给您。
因此,我的解决方案是:
1 。查看模态中的所有焦点元素。
2 .listen更改对网页的关注。
3 。在“焦点侦听器方法”中,可以检查一下,如果模态是打开的,并且焦点元素不存在于焦点元素列表中,则必须焦点焦点元素列表的第一个元素是焦点。
最终代码:
I trying easiest solution present to you.
So my solution is this:
1.finding all focus-able elements in the modal.
2.listen to change focus on the web page.
3.In the focus listener method, it is checked that if modal is open and focused element not exist in the focus-able elements list, first element of focus-able elements list must be focus.
Final code:
将注意力集中在模态中
以将重点放在模态上,您必须将重点放在模态内的聚焦元素上,这就是为什么执行
modal.focus();
并没有导致焦点进入就像您希望的那样,模态不是模态本身并不是一个焦点元素。取而代之的是,您需要做一些事情,例如$(modal).find(“ button”)。fixp()。focus();
而不是。User2495207向您展示了另一种方法,但是
settimeout
容易出现错误,并且不必要。理想情况下,我们也不想规定它应该集中在特定按钮上,只要在选项卡顺序中找到的第一个按钮。但是,这仅解决将重点转移到模态的问题。它不会将焦点捕获到模式中,因此,当您将其选为“最后一个按钮”时,它将焦点转移到模态后面的元素上。
在模式中捕获焦点的
想法是您要检查下一个焦点元素是否在模态内,如果不是在模态之内在模态中。您还应该逆转此逻辑,如果关注第一个按钮并且有人按
shift+tab
将其包装到模态中的最后一个元素,但是我只是要演示第一个方案:<代码>相关图是一个很好的工具,可让您拦截
focus
事件,以确定焦点的前进。因此,在上面的代码中,我们正在检查即将集中的元素(akaressedtarget
)是否在模态内,如果不是,那么我们将焦点强制焦点。关于可访问性的最后一个说明
您还希望确保在
easse> easse>
的键盘上关闭模态。在此注释中,
e.keycode
被弃用,我们都应该使用e.key
。如果您需要支持IE,首先,我很抱歉。其次,它需要
e.keycode
才能正常运行,因此需要与您的e.key
检查,例如e.key = ==“逃脱”&amp;&amp; e.KeyCode ===“ 27”
。但是,我确实建议您可能只是制作一个将事件作为参数接受的函数,并将这些检查保留在该功能中,因此当IE最终支持e.key
时,您可以全部清理代码在一个地方。Moving focus into the modal
To put focus into the modal, you have to put focus onto a focusable element within the modal, which is why doing
modal.focus();
did not result in the focus moving into the modal like you wished since modal itself isn't a focusable element. Instead, you would want to do something such as$(modal).find("button").first().focus();
instead.User2495207 showed you another way to do this, but
setTimeout
is prone to bugs and unnecessary. We also ideally don't want to dictate that it should focus on a specific button, just whichever is the first button found in the tab order.This only solves the problem of moving the focus into the modal initially, however. It does not trap the focus within the modal, so when you tab past the last button, it will move focus to elements behind the modal.
Trapping focus in the modal
The idea here is that you want to check if the next focusable element is within the modal or not, and if not then that means you were on the last element in the modal and need to wrap focus to the first element in the modal. You should also reverse this logic where if the first button is focused and someone presses
shift+tab
it'll wrap to the last element in the modal, but I am just going to demonstrate the first scenario:RelatedTarget
is a great tool that allows you to interceptfocus
events to determine where the focus is going. So in the code above, we are checking if the element that is about to be focused, akarelatedTarget
, is within the modal, if it is not, then we force focus where we want it to go.One last note about Accessibility
You also want to be sure to make the modal close on
keydown
ofEscape
. On this note,e.keyCode
is deprecated, and we should all be usinge.key
.If you need to support IE, first of all, I am sorry. Second of all, it requires
e.keyCode
to function properly so it needs to be used in conjunction with youre.key
check, such ase.key === "Escape" && e.keyCode === "27"
. I do recommend, however, maybe just making a function that accepts the event as a parameter, and keeping these checks within that function so when IE eventually makes support fore.key
then you can cleanup your code all in one spot.