A look at some more complex accessibility challenges

Prerequesites: I will assume you have some basic understandig of accessibility concepts, if you don’t I recommend to read “Part 1: Introduction” and “Part 2: 5 priciples you should start implementing right away” befor you dive into this one.

In the previous post I covered 5 principles that should be quite easy for every developer to start implementing right away. This time we will take a look at some more complex accessibility topics like keyboard traps, focus loops, reduced motion, and hiding things in an accessible manner. After reading this blogpost you should have a better understanding on how to approach these challenges.

Table of contents:

1. Keyboard traps and focus loops

Keyboard navigation is a very important factor of creating an accessible web application. One issue that we have to take into concideration is focus traps and focus looping. I have seen these terms used differently in different articles so here is my definitions of them:

  • Keyboard trap: When the user is able to use the keyboard to navigate to a part of your application, but then can’t navigate back, or out. They are literally trapped.
  • Focus loop: When we want the focus to stay inside a specific area of the application until the user decides to move on. For example in a pop-up/modal.

In generall its important that the tab order on your page follows a logical order, and that every clickable element is available via keyboard navigation. If you have a very large header area with lots of links, it can be usefull to add a “Jump to content” link so the user doesn’t have to tab through everything to get there.

How to avoid keyboard traps

There is no magical solution that will solve all keyboard traps. The best thing is to test as you build, and make sure that every new component is available and works as expected. But there are some things you should keep in mind.

Using this.focus() on an element can potentially make it a trap, so make sure you test it thoroughly if you use it.

<form>
  <label>Name</label>
  <input type="text"></input>
  <label>Focus trap </label>
  <input type="text" onBlur="this.focus()"></input> 
  <label>Unreachable</label>
  <input type="text"></input>
</form>

Another thing that can create a keyboard trap is if you set the focus wrong when dealing with content that is hidden visually but is still a part of the dom and available through keyboard navigation. You should take action to revert the styling that hides the element if the element becomes in focus.

I will cover more about hiding things in an accessible manner later in this blogpost.

How to accomplish focus loops

There are also situations where we would like to ‘trap’ the foucs. The most common example of this is when we have a pop-up form or dialog and the user can tab through the fields in the form. When they reach the end we want the focus to jump back to the start of the pop-up again – not go outside to the content in the background.

We can achive this by adding some javascript that listenes for tab-events and if the item in focus is the last one – then move focus back to the top of the form. Remember to add a way for the user to exit the dialog. This arcticle on css-tricks give a good introduction to focus loops.

2. Accessibility for people with vestibular disorders

At some point in your life you have probably experienced dizziness. Maybe you got up from the couch too fast, or you spun around too quicly? Maybe you have even gotten sick from dizziness?

Imagine if you had a condition that made you feel like that (or worse). Thats the reality for people with vestibular disordes. And sometimes these symptomes can be triggered by motion on a website.

How to work with reduced motion
Modern browsers have a setting “prefers reduced motion” that the user can choose to turn on. There is also a CSS media query that we can use to see if “prefers reduced motion” is set.

@media (prefers-reduces-motion){
  //do things to reduce motion here
}
@media (prefers-reduces-motion: no-preference){
  //do things to create motion here 
}

If your creating motion with javascript you can use window.matchMedia('prefers-reduced-motion') to see if the user has prefered reduced motion on or not. The function will return an object with a property “matches” that will be true if the user has set the prefers reduced motion.

const userPreferReducedMotion = 
window.matchMedia('prefers-reduced-motion');

const reducedMotionSettingListener = () => {
  if(userPreferReducedMotion.matches){
    //do the motion things here
  }
}

userPreferReducedMotion.addListener(reducedMotionSettingListener);

Other things to concider

  • Animations, videoes, sliders or other parts of your website that have motion on it should not start automatically.
  • Don't use gif's or other types of content that the user can't controll/turn off.

3. Hiding things in an accessible manner

You might be thinking something like "Hiding things are easy! Just use 'display: none'! Why is this covered in 'complex topix'?". Well, unfortunatly it's not quite as straight forward when we want make sure the content is available for everyone. If we use 'display:none' the element is not just hidden, it is completely removed from the DOM, and therefor it's not accessible to assisitve technology like screen readers. In some cases thats what we want, but

But with the right approach hiding content can also be very useful for accessibility. We can hide things visually and only display it to screen readers, we can hide content from screen readers and only show it visually, or we can hide content from both.

Hiding things from screen readers

You can use the ARIA attribute "aria-hidden" to hide some content from screen readers. It's worth noticing that this attribute should not be used on focusable content like inputs, buttons and links.

<p aria-hidden="true">
The content of this paragraph will be ignored by screen readers. 
</p>

Hiding things visually but displaying it for screen readers

It can be very usefull to add some extra context or explanation to those who access the page with a screen reader. A common way to do this is to have a class for visually hiding thins, and using this class on the elements you want to hide visualy - but keep accessible to screen readers.

.visually-hidden {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

4. Avoid CSS dependencies for content

If your site depends on CSS to be functional or understandable it can be a big accessibility concern, since most assistive technology ignores CSS completly. Like mentioned in the previous section this can refer to hiding things. But also if you use css to add content to your page like in the example below:

.myClass::before{
   content: "This content is not available for screen readers"
}
.myClass::after{}

Summary

  • The best way to avoid keyboard traps is to consistantly test that every interactive element on your page is accessible with keyboard navigation, and that you can also 'get back out' of a foucs state.
  • Use javascript to keep the focus loop inside a popup/modal.
  • Use the css media queries, or check the window.matchMedia('(prefers-reduced-motion)'), for reduced motion to make your site accessible to people with vestibular disorders.
  • Keep in mind that "display: none" is not always the right way to hide things. And that you can use ARIA attributes or css to hide/display different content to people using a screen reader, and users without visual impairments.
  • Don't use css to add content to your page.

Resources

Did you find this article usefull? Follow me on twitter to be notified when I publish something new!

Also, if you have any feedback or questions, please let me know in the comments below. :)

Thank you for reading, and happy coding!

/Eli

27