I have a component with an html structure like this:
<div class="wrapper">
<div class="view"></div>
<div class="view"></div>
<div class="view"></div>
<div class="view"></div>
</div>
The views are next to each other and the wrapper has full screen size and overflow: hidden
It’s a multi step form, basically a full page slider.
However, when tabbing through the inputs, I can focus input fields that are out of view. What would you guys do to prevent this? display: none
doesn’t really work because it has to be visible in order for the sliding animation to work.
One idea would be to use display: none
but remove it before switching slides.
Another idea would be to just use JS to stop inputs from getting focused if the parent "view" has a specific class
Still, these don’t feel 100% right and a bit hacky. Does anyone know of a solution?
2
Answers
Add
tabindex="-1"
to your element, set this attribute to -1 can make this element unfoucsable.So, you can add/remove this attribute dynamicly
Depending on your usecase, the most robust solution is whether to actually use display:none, or to automatically scroll the element into view when it takes the focus if it isn’t currently visible.
Using display:none is the only way 100% full proof to make sure that the element is both invisible and non-focusable, and to be also sure that, when you remove display:none, it becomes both visible and focusable again.
This is the best solution if all views shouldn’t be accessed at the same time, for example if you have several steps to follow in a logical order, which is probably your case.
Scrolling the element into view when it takes focus is the way to go if the different view can be accessed without a particular order, or more simply, in any order.
Otherwise ssaid, if some of the views are invisible just because the screen is too small to show them all at once.
You can certainly adapt your CSS to run desired animations in this case.
Automatically scroll into view when necessary is better than requiring the user to press previous/next buttons. It simplifies a lot going back and forth for screen reader and keyboard only users, for the kind of forms where you can freely do so and need frequently to.
Don’t use tabindex=-1 or inert for elements out of view. From keyboard accessibility point of view, it will be correct, it won’t be focusable, but it won’t be correct from screen reader accessibility point of view.
The element can’t be reached with tab, but can still be reached when using other screen reader navigation commands in browsing mode (e.g. go to next form field, pick a field in the list of field, or read through with arrow keys). If a screen reader user find your field and try to focus it by pressing enter, he/she won’t understand at all why it doesn’t work and will probably give up quickly.
Other assistive tools can also access the element although it isn’t visible. You may be able to enter text with a voice control and dictation software, for example.
There is a solution, using both tabindex=-1 and aria-hidden=true at the same time. The former will prevent focus with tab, the later will hide the element from the screen reader.
The big problem with this solution is that you must be extremely cautious: whether both of the attributes must be present, or both must be absent. If one of them is present and not the other, then accessibility is broken.
Unfortunately, very often, aria-hidden is forgotten and stays there forever for no reason when tabindex=-1 and/or inert have been removed. It isn’t simple to catch it, because it has no perceivable impact if you don’t test with a screen reader.
Since very few people actually test with a scren reader, accessibility is easily broken without anyone ever noticing it. Therefore, I wouldn’t recommend this possibility.
So, sorry, but display:none is the most robust, and the simplest solution.
I’m pretty sure you can adapt your CSS.