chrome://accessibility
visually-hidden
class to ensure it is out of the flowopacity: 0;
will reserve the space in the document flowdisplay: none;
won't render the toolvisibility: hidden;
is a use CSS tool to ensure tabbing can get there that reserves the space but takes the a11y informationThe chrome://accessibility
gives you the option to turn on the accessibility tree. The Chrome Dev tools these days lets you move away from it but it is good to know it exists.
It shows you how the CSS and JS can impact the accessibility tree.
A "hack" to help you check focus in a tab:
document.body.addEventListener('focusin', event => { console.log(document.activeElement); });
Just pop it inside the Chrome console and is great to show what is in focus.
These topics consisit of:
Make non-interactive elements focusable
tabIndex = '0'; // in the tab order, see following slides tabIndex = '-1'; // focusable by script, or removes from tab order tabIndex = '99641'; // all up in your tab order - hard to manage
Screen readers go beyond the TAB key
aXe will warn you when you use a possible tab index because of the management
Make custom controls fully interactive. A lot of the important information here was the HTML semantics.
<div tabindex="0" role="button" aria-label="Close" onClick="{clickHandler}" onKeyDown="{keyboardHandler}" ></div> <!-- or just use a button! --> <button aria-label="Close" onClick="clickHandler"></button>
aria-hidden="true"
strips a11y informationtabindex="-1"
stop things from tabbinginert
- HTML attribute to stop aria regionsdisplay:none;
just hide it completely/* avoid */ *:focus { outline: none; } /* do */ :hover, :focus { outline: 5px auto blue; }
There is a polyfill as well for CSS based on the mouse.
:focus:not(.focus-visible) { outline: none; } :focus-visible { outline: 5px auto blue; }
There is also a what-input
module.
// in a layout or component import 'what-input' // in css [data-whatintent="mouse"] *:focus { outline: none }
What would be ideal is an OS-level preference.
It would be ideal to give users a class friendly name they can hook into so they can use their own user-friendly style sheets.
Here Marcy is making us of useRef
to set a ref for a component and help define the toggling and focus elements!
Here is using useEffect
based on a state change to toggle focus for an element.
She goes the hacky was way of using componentRef.current.querySelector('a').focus()
.
A quick mention that
document.addEventLister
anddocument.removeEventLister
need to be used with care to ensure there is no memory leak.
Marcy also uses a nice little tidbit of componentRef.current.contains(event.target)
from an event handler during an if statement.
The final code can be seen here
The
ul
needed to have therole="list"
again for Safari due it is removing the role based on how people are using their CSS to removeul
bullet styles etc.
$refs
A cool tidbit here is that Marcy uses the router meta data on a change to help dictate if the skip link should be focused.
There is a nice little sandbox you can use to test an onRouteChange
type handler for a Gatsby example
Nice patterns to follow to notify assistive tech users without moving focus:
You can create the announcements using ARIA live regions (with reference here
<div role="status"></div> <div role="alert"></div> <div aria-live="polite"></div> <div aria-live="assertive"></div>
Message command centers of varying importance
Live region gotchas and tips:
There is a codepen
prefers-reduced-motion
CSSThere is a nice CodePen to see the prefers-reduced-motion
in action here
Emphasize core web page content first, then add layers of presentation and features on top as browsers/connections allow:
Testing for quality live in a file or on a commit, you can use eslint-plugin-jsx-a11y
.
An interesting test that Marcy uses:
const activator = getByTestId('id'); activator.focus(); // will only pass if element is focusable // also great when you emulate clicks and test // focus to change expect(activator).toHaveFocus();
Find the example from the video here