问题
I have a modal popup opened. I have accessibility requirement. So added ARIA related labels. But when i click tab key continuously focus going to the page behind the actual page.
Added role="dialog" in html file
But when modal opened i want only the focus navigate within the modal popup.
Working on Angular4, HTML5
project. Better if we find a solution within HTML file itself. I mean without added any javascript/jQuery related stuffs to prevent this
回答1:
You are asking about focus trap, it's nicely demonstrated in this demo: http://davidtheclark.github.io/focus-trap/demo/
Adding role="dialog"
will not automatically provide trap the focus within that element. In fact, there's no native focus trap provided by browsers.
You need to go with one of following options:
- implement focus trap by yourself
- use 3rd party solutions of focus trap, e.g. https://github.com/davidtheclark/focus-trap
- use 3rd party solutions of modal windows, e.g. https://github.com/sweetalert2/sweetalert2 which is fully compatible with WAI-ARIA specifications and provide focus trap for you
回答2:
be careful of any method relying only on javascript events as it won't correctly handle screenreaders
However, this cannot be achieved without javascript like already indicated in multiple questions like How to keep focus within modal dialog?
You have three steps to do:
1. disable screenreader interaction with any other nodes by setting aria-hidden=true
on them
For instance:
<main aria-hidden="true"><!-- main content here--></main>
<dialog>Your dialog here</dialog>
2. disable any keyboard interaction with them
This has to be done in Javascript / or jQuery.
This is a one-liner instruction in jQuery, using jquery-ui
$("main :focusable").addClass("disabled").attr("tabindex", -1);
The reverse can be achieved using:
$(".disabled").removeClass("disabled").attr("tabindex", 0);
3. remove any pointer event for those elements to disable mouse interaction
css sample:
main[aria-hidden='true'] { pointer-events: none;}
回答3:
Here's my solution. It traps Tab or Shift+Tab as necessary on first/last element of modal dialog (in my case found with role="dialog"
). Eligible elements being checked are all visible input controls whose HTML may be input,select,textarea,button
.
$(document).on('keydown', function(e) {
var target = e.target;
var shiftPressed = e.shiftKey;
// If TAB key pressed
if (e.keyCode == 9) {
// If inside a Modal dialog (determined by attribute role="dialog")
if ($(target).parents('[role=dialog]').length) {
// Find first or last input element in the dialog parent (depending on whether Shift was pressed).
// Input elements must be visible, and can be Input/Select/Button/Textarea.
var borderElem = shiftPressed ?
$(target).closest('[role=dialog]').find('input:visible,select:visible,button:visible,textarea:visible').first()
:
$(target).closest('[role=dialog]').find('input:visible,select:visible,button:visible,textarea:visible').last();
if ($(borderElem).length) {
if ($(target).is($(borderElem))) {
return false;
} else {
return true;
}
}
}
}
return true;
});
回答4:
Right now also Angular CDK provides directive to add focus trap to the modal popup https://material.angular.io/cdk/a11y/api#CdkTrapFocus
回答5:
the parent dialog element should have role="dialog"
to indicate this is a dialog.
In your case, you're also missing the aria-modal="true"
which should tell the browser and screen readers that the focus should stay only within the modal.
Using aria-modal="true"
replaces the need to add aria-hidden="true"
for elements that should be hidden from screen readers and not receive keyboard focus outside the modal while the modal is open.
If the above method does not work, you may still want to use aria-hidden="true"
for the parent element outside the modal to prevent keyboard from leaving the modal.
If for some reason that still does not work and you need manual control over keyboard focus, you can check which elements receive keyboard focus outside the modal and then set their tabindex attribute to tabindex="-1"
, meaning they can still receive focus but not from the keyboard. In this approach you need to be careful, because when the modal closes you'll want to restore the functionality by either removing the tabindex="-1"
from those elements or by setting it back to tabindex="0"
Source: W3C wai aria practices - dialog modal with example
来源:https://stackoverflow.com/questions/50178419/how-can-restrict-the-tab-key-press-only-within-the-modal-popup-when-its-open