[英]HTML Accessibility tab not works as expected
I have a form with 3 input
element.我有一个带有 3 个input
元素的表单。 the accessibility team requires to focus the element on tab press
.可访问性团队需要将元素集中在tab press
。 it works well.它运作良好。 event doing well by shift+tab
as well.事件通过shift+tab
也做得很好。 but the issue is after the submit button reached by focus they want to continue from first input element instead of leaving the page and focusing the address bar.但问题是在焦点到达提交按钮后,他们希望从第一个输入元素继续,而不是离开页面并聚焦地址栏。
Is it possible?是否可以? how can i make focus to loop my form in tab
and shif+tab
instead of moving out?我怎样才能让焦点在tab
和shif+tab
循环我的表单而不是移出?
I am showing the form in popup
modal.我在popup
模式中显示表单。
<form action="/action_page.php"> <label for="fname">First name:</label><br> <input tabindex="1" type="text" id="fname" name="fname" value="John"><br> <label for="lname">Last name:</label><br> <input tabindex="2" type="text" id="lname" name="lname" value="Doe"><br><br> <input tabindex="3" type="submit" value="Submit"> </form>
2a. 2a. If it is within the / etc. are you able to move it outside of that.如果它在 / 等范围内,您是否可以将其移到该范围之外。 => it's sitting outside out it already. =>它已经坐在外面了。 because the popup page based因为弹出页面基于
Thanks for answering the questions, hopefully the following explanation will highlight why I was asking them (and then I will offer some solutions).感谢您回答问题,希望以下解释能突出我问他们的原因(然后我将提供一些解决方案)。
Screen reader users don't navigate using only the tab key.屏幕阅读器用户不会仅使用 Tab 键进行导航。 Depending on the screen reader they use they use different shortcuts to navigate via headings, links, forms etc.根据他们使用的屏幕阅读器,他们使用不同的快捷方式通过标题、链接、表单等进行导航。
This causes accessibility issues with popups as people only tend to capture the tab key.这会导致弹出窗口的可访问性问题,因为人们只倾向于捕获Tab键。 Then if a user uses a shortcut, eg 2 in NVDA to jump through heading level 2s on the page they can end up outside of the modal without knowing it exists, often without any way to get back into the modal without tabbing around for ages.然后,如果用户使用快捷方式,例如 NVDA 中的2跳过页面上的标题级别 2,他们可能会在不知道它存在的情况下结束模态,通常没有任何方法可以回到模态而不用长时间切换。
So the solution is obvious, make sure nothing else on the page is accessible (not just not focusable).所以解决方案很明显,确保页面上没有其他内容可访问(不仅仅是不可聚焦)。
However you need to have your DOM structure well ordered / organised to make this manageable.但是,您需要对 DOM 结构进行良好的排序/组织以使其易于管理。
display:none
on all other elements).我们希望保持相同的视觉设计(即我们不能只在所有其他元素上使用display:none
)。As we cannot intercept key presses to manage focus within the modal we have to make every other element (other than those in the modal) completely inaccessible while the modal is active.由于我们无法在模态中拦截按键来管理焦点,因此我们必须在模态处于活动状态时使所有其他元素(除了模态中的元素)完全无法访问。
aria-hidden="true"
is effectively display: none
for screen readers. aria-hidden="true"
有效地display: none
用于屏幕阅读器。 Support for aria-hidden
is good at around 90% to 95% for all screen reader / browser combos.对于所有屏幕阅读器/浏览器组合,对aria-hidden
支持大约为 90% 到 95%。
To make the content outside of the modal inaccessible we need to add aria-hidden="true"
to every element outside of the modal as well as tabindex="-1"
to ensure that nothing can be focused outside of the modal using the tab key.为了使模态之外的内容无法访问,我们需要向模态外的每个元素添加aria-hidden="true"
以及tabindex="-1"
以确保使用选项卡不会将任何内容聚焦在模态之外钥匙。
I asked about your document structure as the easiest way to implement this is on regions / main landmarks.我询问了您的文档结构,因为实现这一点的最简单方法是在区域/主要地标上。
So when the modal is active we need to add aria-hidden="true"
and tabindex="-1"
to the <head>
, <main>
, <footer>
etc. By doing it at the landmark level and by putting the modal outside of the main document flow this becomes easy to manage and maintain while preserving semantic HTML markup.因此,当模态处于活动状态时,我们需要将aria-hidden="true"
和tabindex="-1"
到<head>
、 <main>
、 <footer>
等。通过在地标级别执行此操作并将在主文档流之外使用模态,这变得易于管理和维护,同时保留语义 HTML 标记。 The opposite is true of the modal (so hide it using the same technique when it isn't active.)模态的情况正好相反(所以当它不活动时使用相同的技术隐藏它。)
Before modal open模态打开前
<head aria-hidden="false"></head>
<main aria-hidden="false"></main>
<footer aria-hidden="false"></footer>
<div class="modal" aria-hidden="true" tabindex="-1"></div>
Modal open模态打开
<head aria-hidden="true" tabindex="-1"></head>
<main aria-hidden="true" tabindex="-1"></main>
<footer aria-hidden="true" tabindex="-1"></footer>
<div class="modal" aria-hidden="false"></div>
Note how I have aria-hidden
always added as some screen readers do not react well to dynamic addition of aria
(they react fine to changing properties though).请注意我是如何始终添加aria-hidden
因为某些屏幕阅读器对aria
动态添加反应不佳(尽管它们对更改属性反应良好)。
For this I think it will be easiest to share the code I use to trap focus within a modal.为此,我认为最容易分享我用来在模态中捕获焦点的代码。
The purpose of the below function is to focus the first focusable item within a modal when it opens, store a reference to the element that activated the modal (as we want to return the user there when the modal closes) and to manage focus.以下函数的目的是在模态打开时将第一个可聚焦项聚焦,存储对激活模态的元素的引用(因为我们希望在模态关闭时将用户返回到那里)并管理焦点。
Please note that I use a micro library to enable jQuery style selectors so you may need to tweak things for your use.请注意,我使用了一个微型库来启用 jQuery 样式选择器,因此您可能需要调整一些东西以供您使用。
The item
variable is the referring button that was pressed before opening the modal (so we can return focus there after closing the modal). item
变量是在打开模态之前按下的引用按钮(因此我们可以在关闭模态后将焦点返回到那里)。
The className
variable is the class name of the modal so you can target different modals. className
变量是模态的类名,因此您可以针对不同的模态。
kluio.helpers
is just an array of functions I use across the site so can be omitted. kluio.helpers
只是我在整个站点中使用的一组函数,因此可以省略。
kluio.globalVars
is an array of global variables so could be substituted for returning the results from the function. kluio.globalVars
是一个全局变量数组,因此可以替换为从函数返回结果。
I have added comments to each part to explain what it does.我在每个部分都添加了注释来解释它的作用。
The setFocus
function is called when the modal is opened passing in the element that was pressed to activate it and the modal's className
(works for our use case better, you could use an ID instead). setFocus
函数在模态打开时调用,传递按下以激活它的元素和模态的className
(更适合我们的用例,您可以使用 ID 代替)。
var kluio = {};
kluio.helpers = {};
kluio.globalVars = {};
kluio.helpers.setFocus = function (item, className) { //we pass in the button that activated the modal and the className of the modal, your modal must have a unique className for this to work.
className = className || "content"; //defaults to class 'content' in case of error ("content" being the class on the <main> element.)
kluio.globalVars.beforeOpen = item; //we store the button that was pressed before the modal opened in a global variable so we can return focus to it on modal close.
var focusableItems = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', '[tabindex="0"]']; //a list of items that should be focusable.
var findItems = [];
for (i = 0, len = focusableItems.length; i < len; i++) {
findItems.push('.' + className + " " + focusableItems[i]); //add every focusable item to an array.
}
var findString = findItems.join(", ");
kluio.globalVars.canFocus = Array.prototype.slice.call($('body').find(findString)); //please note we use a custom replacement for jQuery, pretty sure .find() behaves identically but just check it yourself.
if (kluio.globalVars.canFocus.length > 0) {
setTimeout(function () { //set timeout not needed most of the time, we have a modal that is off-screen and slides in, setting focus too early results in the page jumping so we added a delay, you may be able to omit this.
kluio.globalVars.canFocus[0].focus(); //***set the focus to the first focusable element within the modal
kluio.globalVars.lastItem = kluio.globalVars.canFocus[kluio.globalVars.canFocus.length - 1]; //we also store the last focusable item within the modal so we can keep focus within the modal.
}, 600);
}
}
We then intercept the keydown
event with the following function to manage focus.然后我们使用以下函数拦截keydown
事件来管理焦点。
document.onkeydown = function (evt) {
evt = evt || window.event;
if (evt.keyCode == 27) {
closeAllModals(); //a function that will close any open modal with the Escape key
}
if (kluio.globalVars.modalOpen && evt.keyCode == 9) { //global variable to check any modal is open and key is the tab key
if (evt.shiftKey) { //also pressing shift key
if (document.activeElement == kluio.globalVars.canFocus[0]) { //the current element is the same as the first focusable element
evt.preventDefault();
kluio.globalVars.lastItem.focus(); //we focus the last focusable element as we are reverse tabbing through the items.
}
} else {
if (document.activeElement == kluio.globalVars.lastItem) { //when tabbing forward we look for the last tabbable element
evt.preventDefault();
kluio.globalVars.canFocus[0].focus(); //move the focus to the first tabbable element.
}
}
}
};
Finally in your version of the closeAllModals function you need to return focus to the referring element / button.最后,在您的 closeAllModals 函数版本中,您需要将焦点返回到引用元素/按钮。
if (kluio.globalVars.beforeOpen) {
kluio.globalVars.beforeOpen.focus();
}
The line kluio.globalVars.canFocus[0].focus();
行kluio.globalVars.canFocus[0].focus();
is called to set focus to the first focusable item within the modal once it is activated, you shouldn't need to tab into the first element when it opens it should be automatically focused.被调用以将焦点设置到模态中的第一个可聚焦项,一旦它被激活,当它打开时,您不需要 Tab 进入第一个元素,它应该自动聚焦。
Point 5 is covered by the line kluio.globalVars.beforeOpen = item;
第 5 点被kluio.globalVars.beforeOpen = item;
行覆盖kluio.globalVars.beforeOpen = item;
to set a reference to the item that opened the modal and kluio.globalVars.beforeOpen.focus();
设置对打开模态和kluio.globalVars.beforeOpen.focus();
的项目的引用kluio.globalVars.beforeOpen.focus();
within the close function to return focus to that item.在 close 函数中将焦点返回到该项目。
Point 6 is covered within the document.onkeydown
function starting at if (kluio.globalVars.modalOpen && evt.keyCode == 9) {
.第 6 点包含在document.onkeydown
函数中,从if (kluio.globalVars.modalOpen && evt.keyCode == 9) {
。
I hope all of the above is clear, any questions just ask, if I have time later I will turn it all into a fiddle.我希望以上所有内容都清楚,任何问题都可以问,如果以后有时间我会全部变成小提琴。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.