A look at some more complex accessibility challenges
Tags: a11y, html, javascript
Published: 2021-06-23 07:56:20

> Prerequesites: I will assume you have some basic understandig of accessibility concepts, if you don’t I recommend to read “[Part 1: Introduction](https://dev.to/elischei/change-your-approach-to-accessibilty-and-get-a-better-developer-experience-and-create-more-accessible-websites-b6b)” and “[Part 2: 5 priciples you should start implementing right away](https://dev.to/elischei/web-accessibility-for-developers-part-two-5-principles-you-can-start-implementing-now-1dm0)” 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](#1-keyboard-traps-and-focus-loops)
[2. Accessibility for people with vestibular disorders](#2-accessibility-for-people-with-vestibular-disorders)
[3. Hiding things in an accessible manner](#hidingthings)
[4. Avoid CSS dependencies for content](#4-avoid-css-dependencies-for-content)
[Summary](#summary)

## 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.
```html
<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>
```

I have created [a codepen here if you want to see the above code in action](https://codepen.io/elischei/pen/gOmBOLj).

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](https://css-tricks.com/a-css-approach-to-trap-focus-inside-of-an-element/).

## 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.
```css
@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.

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

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

userPreferReducedMotion.addListener(reducedMotionSettingListener);
```

<!-- wp:paragraph -->
<p><strong>Other things to concider</strong></p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul id="block-3a62ca8d-b68d-4528-bbf8-ff7cc4e23336"><li>Animations, videoes, sliders or other parts of your website that have motion on it should <em>not </em>start automatically.</li><li>Don't use gif's or other types of content that the user can't controll/turn off. </li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2 id="hidingthings">3. Hiding things in an accessible manner</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>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 </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>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. </p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Hiding things from screen readers</h3>
<!-- /wp:heading -->

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

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


<!-- wp:heading {"level":3} -->
<h3>Hiding things visually but displaying it for screen readers</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>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. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><a href="https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/" target="_blank" rel="noreferrer noopener" title="https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/">The a11y project have an article about this</a> where they use the clip attribute like shown below to create the visually-hidden styling. </p>
<!-- /wp:paragraph -->

```css
.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:

```css
.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
* [Keyboard access](https://www.csun.edu/universal-design-center/web-accessibility-criteria-keyboard-access) (Universal design center)
* [How to trap foucs inside of an element](https://css-tricks.com/a-css-approach-to-trap-focus-inside-of-an-element/) (CSS tricks)
* [Introduction to prefers reduced motion media query](https://css-tricks.com/introduction-reduced-motion-media-query/) (CSS tricks)
* [A primer to vestibular disorders](https://www.a11yproject.com/posts/2013-05-15-understanding-vestibular-disorders/) (a11yproject)
* [Visually hidden](https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/) (a11t project)

***
Did you find this article usefull? [Follow me on twitter](https://twitter.com/acupof_dev) 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