Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide all elements from screen readers except one div?

I have implemented a popup that is triggered from a button on my webpage. This popup nearly fills the entire screen and prevents users from interacting with anything on the webpage until the popup is dismissed. This works well for sighted users, but when using VoiceOver on the Mac you can still navigate the underlying web page content, and the blind user would have no idea a popup window was presented.

How can I prevent VoiceOver from navigating every element on the page except for one div (and every element in that div)?

I know one can use aria-hidden="true" to hide it from screen readers, and I know one can force a focus on an element, but I'm not sure how best to accomplish this. Do I need to loop over the entire DOM and essentially hide everything then upon close unhide everything? Or is there a better approach, some ARIA property that defines this type of element that's presented perhaps?

A website that exhibits the desired behavior is Piazza. When you activate the Login button it presents a popup modal dialog and demands focus, and you can't navigate away from it until you dismiss the popup.

like image 962
Jordan H Avatar asked Jan 10 '23 05:01

Jordan H


1 Answers

Implementing accessible modal dialogs correctly has got to be one of the trickier aspects of web accessibility, since there's just so many things to watch out for, on top of the usual issues of screenreader and browser compat and adherence to spec. Here's a summary(!), somewhat based on personal experience, this article from Smashing Magazine on accessible Modal dialogs, WAI-ARIA 1.0 Authoring Best Practices and this slideshow on the same topic.

(Note that you'll find some conflicting advice between these; this is somewhat due to differences in behavior between screenreaders/browsers and spec, and different authors having different positions on whether to stick to spec vs work with the screenreaders that real users actually use.)

  • Tell screenreaders it's a dialog: Add role="dialog" to the parent DIV, and set aria-labelledby to point to the ID of the title.

    This causes the screenreader to recognize the piece of UI as a dialog in the first place; when the user navigates into it, either by navigating or because focus moves into it, the screenreader will announce that the user is now in a dialog, and will likely also announce the title. (On some screenreader/browser combinations - notably VoiceOver+Safari, it may also affect how screenreader navigation works.) This alone does not 'hide' any of the other UI on the page, however.

  • Add basic keyboard support

    There's a bunch of things to do here that are important for both screenreader users and non-screenreader using keyboard users. Two key issues here are to move focus to somewhere appropriate in the the dialog when it initially appears, and when the dialog is dismissed, restore focus back to where it was when the dialog originally appeared.

  • Make it modal for screenreader users and keyboard users

    Dialogs come in two flavors: modal, which don't let the user interact with any other UI while present, and modeless, which do let the user leave the dialog and return later - examples might be the "Find Text" dialogs in some text editors. role="dialog" doesn't distinguish between these two cases, and also using ARIA doesn't have any affect on browser behavior, so if your dialog is modal, you have to do extra work yourself to make it behave as modal. There's two aspects to this:

    • Just as modal dialogs use a gray scrim or blur effect to visually hide the inactive background from sighted users, we also want to hide this content from screenreader users: otherwise they will still be able to navigate out of the dialog to the background, or use other hotkeys to list links or headings or other controls from the page and will see both items from the background part of the page and the dialog. In the past, putting aria-hidden="true" on all other top-level DIVs was the best tool to use to do this (and a bit fiddly - remember to remove it when done!), but as of 2020, aria-modal="true" appears to be decently supported and is much easier to implement.

    • For both screenreader users and non-screenreader-using keyboard users, you also need to make the keyboard behavior modal: hitting tab from the last item in the dialog should wrap to the top of the dialog, and the inverse behavior for shift-tab. If you don't do this, keyboard - and screenreader - users can simply tab right out of your dialog into the background of the page. There's different approaches for doing this, most involve tracking focusin or similar at the body level, and forcing focus back into the dialog if it "escapes".

  • Other tweaks/fixes/hacks

    Windows-based screenreaders such as NVDA and JAWS go into "application mode" when they enter a dialog: their web navigation hotkeys no longer work, and they treat the content of the dialog as a form rather than a rich web page. This is fine is the dialog content is a classic form with just fields, labels and buttons, but isn't a good fit if the dialog contains web content with text, hyperlinks, and the like. In that case, you might want to place a <div role="document">...</div> within your role="dialog" but wrapping the main content.

  • Ensure dialog content is itself accessible

    Should go without saying, but all of the above counts for nothing unless the content within the dialog is itself accessible.

  • Most importantly: understand why you are making the dialog accessible in the first place, and test appropriately.

    Unfortunately, at the moment (Jan 2015!) there's still a lot of variation in behavior between different screenreaders (also depending in browser used); it's almost like how browsers were with CSS a decade(!) or so ago. It's worth understanding why you want to make your UI accessible, figure out where most of your users are going to be, and test appropriately given the screenreaders they'll be using. From the most recent (Jan 2014) WebAim Screenreader survey, Windows readers - notably JAWS and NVDA - have the majority of the market, with VoiceOver coming third.

    Here's one possible strategy to consider:

    • If you just want to do a basic 'due diligence', then testing with just VoiceOver may be fine. The experience may not be as good on the other screenreaders, but if something works with VO, it's likely not going to be completely broken on the others.

    • Next level up is to get a copy of (free, but feel free to donate) NVDA windows-based screenreader and run it in a VM on a Mac (assuming you're using a Mac here). NVDA and JAWS tend to be pretty close behavior-wise.

    • If accessibility is part of your job description, then likely you or your company will need to get a copy of JAWS ($800+!), since that appears to be the screenreader of choice for government and educational institutions. (This is perhaps the accessibility analog of testing with downlevel versions of IE!)

like image 94
BrendanMcK Avatar answered Jan 18 '23 19:01

BrendanMcK