People who write standards are very cleverly settled. It is enough for them to write how everything should work well, and then not their problems.
Something like this turned out to be “how the dialogues should work,” or rather the “correct” modal dialogues from the point of view of a11y.
In the description of the
dialog role on MDN, everything is written very simply:
')
- The dialog must be properly labeled
- Keyboard focus must be managed correctly
The problem is that MDN has forgotten about another important point, and the rest have forgotten one of the things they said - that the modal should not let the focus out of its hands. The active element must be put under lock. Do not let him escape from our trap.

Modal dialog
The story began quite recently - in the Web Standards Newsletter I got a link to the “correct”
WAI-ARIA Dialog . And away we go.
The component is really good:
- it hangs aria-hidden on the page to hide content from screen-readers (works only in the first example).
- it obscures the content and cuts down the scrolling page.
- controls the focus so that the modal cannot be tabooed.
- after closing the dialog, it returns focus to the original position.
- and adds different aria-specific tags, of course.
Those he does everything that asks for MDN and even more, since without the first item to “get out” of the dialogue with the activated screen reader it is not difficult.
In general - must have!

Focus
But the implementation of "
focus-management " is a little disappointing - the guys actually intercept keyboard events (and not only) and
emulate the tab button themselves.
It is so incomprehensible to the mind that I decided to dig a little as “this” should work at all. The word "dig" means to check how different sites and frameworks handle tabs.
Let's start with the sites (a bit biased sample):
- Google Gmail | G + - perfect. ️
- Classmates - with the departure of taba they close the modal, to which the focus never comes
- FB - depends on the page. In the group / on the personal page - there is nothing, at the time of writing messages is. Never zhmakayte Tab (in safari) on the main - the roof blows.
- VK - “randomly” page ignores tab
- Yandex.Maps - the page completely ignores the tab
- Yandex.Music - the page completely ignores the tab
- YAN - no focus management.
- LiveJournal - no focus management.
- My own sites - no focus management.
- Habrahabr - no focus management, modals
- Jira / Confluence - perfect. ️
The conclusion is simple - the “normal” sites lack a bit of brains, and Yandex's hands are torn off.
With frameworks (a bit biased sample) is much more interesting:
With frameworks it appears too absolutely bad. And absolutely no one, no one hangs aria-hidden on the rest of the content to make the modal
really accessible to people who are forced to use screen readers.
Oftopik
In fact, I also didn’t bother at all with all this garbage, but then, as an evil, my dear wife decided to learn how to design in the HTML Academy where
pepelsbey with a big, big company made her and me think about the question of how
tabby my site is.
I had to learn a new science and solve a problem with a focus.
PS: Vadim recommends scoring on all this aria-hidden with focus-management and using the html inert attribute, which simply “turns off” (just completely) everything except the modal and there will be no problems with either the screen / reader or the focus.
Although I’m not sure about the second one, it’s still not working very well, and the polyfiles are terrifying .....
Focus lock
In general, as Leo Tolstoy said on the street ... -
and what are your suggestions ?
In fact, the problem is very simple - despite the fact that millions of modules were written for JS - there are actually no modules for focus management.
- focus-manager is a simple focus-manager with a simple vanilla API and a great example . There are a couple of minuses
- ToleFocus is some kind of monster from which you want to run.
- react-focus-trap is so simple that it returns focus only to the beginning.
- Focus manager from AUI, but who had heard about AUI before?
- focus-trap , which is also focus-trap-react, which was used in the WAI-ARIA demo at the beginning of the article. And which is turned off by default by Esc and generally does not use the DOM-API correctly
In general,
7 troubles = +1 new bike . Or rather a real train from
focus-lock ,
dom-focus-lock ,
react-focus-lock and
vue-focus-lock - for all occasions.
From the side of the wrapper (react, vue, dom), everything is very simple - get the DOM node and close the focus in it. All salt in focus-lock.
There are several reasons for creating a new library:
- Unfortunately, all solutions (except focus-trap / lock) completely ignore tabIndex and become completely inoperable if one smart programmer breaks the tab order.
The case, of course, is a bit synthetic, but quite real. To my great regret. - Of all the solutions (except focus-trap / lock and react-focus-trap), you can easily tabulate the safari (JFYI: safari distinguishes between Tab and Opt + Tab). And if the focus leaves the trap once, no one will return it back.
- focus-trap, which works so well everywhere, does it because it intercepts and emulates a Tab, which completely ignores the settings of the same Safari with the item above.
- All solutions (except focus-lock and BluePrint.js) select the first element at the input, not the autofocus element.
PS: focus-trap is looking for an element with an initialFocus attribute. Why?
So I had to make another bike, which temporarily responds to a slightly larger list of whistles than its closest competitors. Or specifically to all.
Just wrap modals (and not only modals) in FocusLock - and half of the problems will be solved.
React-focus-lock
demo -
codesandbox.io/s/jvl0k6zyk3 (
find the difference ).
Vue-focus-lock
demo -
codesandbox.io/s/l5qlpxqvnq<FocusLock> <Modal> any data </Modal> </FocusLock>
But only half, since aria-hidden (or inert) will have to be hung up by someone else and somewhere else. But that's another story.
Total
Total do not forget% username%, that modals are not only a gray lightbox, which is not clicked by the mouse, but also a wondrous world of keyboard exercises.
But most importantly - do not forget that you should not interfere with the user to operate with the site not only with the mouse.
PS: Better yet, turn on VoiceOver or another ScreenReader and try your sites for durability. Be surprised.
Many things, for example, “manual keyboard navigation” in Yandex Mail, defacto does not change the active element.
One programmer from Finland Yandex just lost as a user.
PPS: Gmail, however, is not so much better.
In general - do not get caught -
github.com/theKashey/react-focus-lock