HTML

Accessibility

Tips on improving the usability of a website.

Tags

accessibilitydebuggingnavigationariamotiontest

Debugging

First Steps

Keyboard Navigation

Not all users use a mouse.

Shortcuts

Make a list of keyboard shortcuts for navigating the site and accessing its various items.

Define custom key bindings that are intuitive.

Tabbing

Native Navigation

tab next item

shift + tab previous item

Cycles through the following tags

<a>

<button>

<input>

<select>

<textarea>

<iframe>

Does not cycle through most other tags

<div>

<section>

Tab Index

Make any element able to be tabbed into, focusable.

tabindex="n"

n is hierarchy order

Skip Links

A link that steps over a group of links that otherwise would be tabbed into and cycled through.

Useful for helping users skip over navigation and go directly into some main content.

HTML

<a href="#maincontnet" class="skip-link">
  skip to main content
</a>

<div class="navigation">
  navigation buttons
</div>

<div id="maincontent" tabindex="-1">
  main content
</div>

CSS

#skip-link {
  position: absolute;
  top: -40px;          // I prefer not to hide it , to not confuse anyone
  z-index: 1000;
}

#skip-link:focus {
  top: 0;
}

Good Practice

Use skip links for navigation and other elements similarly repeated across pages.

Hidden vs Visible Elements

Renders in DOM but visually hidden.

Reader accessible.

Useful for including screen reader text.

.visually-hidden {
  border: 0;
  clip: rect(0 0 0 0);
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
}

Renders in DOM but visually hidden. Accessible.

Reader accessible.

.opacity {
  opacity: 0;
}

Removed from DOM.

Not reader accessible.

.displayNone {
  display: none;
}

Renders in DOM but visually hidden.

Not reader accessible.

.visibility {
  visibility: hidden;
}

Custom Focusable Elements

Once an element is made to be focusable, add accessibility info to the element.

<div tabIndex="0" role="button" aria-label="Close"></div>

Also add accessible controls.

<div tabIndex="0" role="button" aria-label="Close" onClick={clickHandler} onKeyDown={keydownHandler}></div>

Focus

Debugging

Write this on chrome or firefox console with a website to inspect open.

document.body.addEventListener('focusing',(event) => {
  console.log(document.activeElement)
});

Save Focus Location

var currentElement = document.activeElement; saves the users current focus location , useful for returning back to where they left off

Tab Trapping

Restrict tabbing to focus only on certain contained elements.

if (document.activeElement === firstTabStop) {
  e.preventDefault();
  lastTabStop.focus();
}

Example of pop up modal containing navigation elements.

var modal = document.querySelector(".focus-modal");
var modalButton = document.querySelector(".focus-moda-buttonl");
var modalOverlay = document.querySelector(".focus-modal-overlay");
var cancelButton = document.querySelector(".focus-modal-cancel");

modalButton.addEventListener('click,open');
cancelButton.addEventListener('click,close');

function open() {
  var previouslyFocused = document.activeElement;
  
  // list of elements to focus , there are many more than listed here
  var focusableElements = modal.querySelectorAll('a[href],area[href],select:not[disabled]');
  focusableElements = Array.prototype.slice.call(focusableElements);
  
  var firstItem = focusableElements[0];
  var lastItem = focusableElements[focusableElements.length - 1];
  
  modal.addEventListener('keydown',trap);
  // show modal
  modal.style.display = "block";
  modalOverlay.style.display = "block";
  
  function trap(event) {
    console.log(event.keycode) // shows keycode of button pressed to use below
    if (event.keyCode === 9) {
      if (event.shiftkey) {        // moving backwards
        if(document.activeElement === firstItem) {
          event.preventDefault();
          lastItem.focus();
        }
      }
      else {                   // moving forwards
        if(document.activeElement === lastItem) {
          event.preventDefault();
          firstItem.focus();
        }
      }
    }
    else if (event.keycode === 27) { // escape key pressed
      close();
    }
  }
}

function close() {
  // hide modal
  modal.style.display = "none";
  modalOverlay.style.display = "none";
}

Disable Focus On Elements Under A Modal

<div aria-hidden="true" tabindex="-1"></div>

Focus Styles

Do not remove focus outline.

Instead customize the focus outline.

I may want to use an inset drop shadow.

:hover, :focus {
  outline: 5px auto brandColour;
}

Screen Readers

Alt

img src="some.png" alt="some description"/> no need to write image of

alt="" skips element , such as purely decorative elements

alt="SOME DESCRIPTION" words in all caps are read letter by letter

Audio & Video

Provide a descriptive text transcript.

Hidden Elements

Screen readers do not read any elements with the following attributes.

display: none;

visibility: hidden;

<input hidden/>

Semantic HTML

<html lang="en"> declares language for page

<quote lang="ru"/> declares language for the quote

Use only one H1 tag per page.

ARIA

Role

Attribute that semantically describes the element.

Useful for older browsers.

<article role="article">some text</article>  // what new browsers see
<div role="article">some text</div>          // what older browsers see

Label For

Label for the element it appears in.

<label for="username">Your user name</label>
<input type="text" id="username">

Label By

Useful for differentiating between a shipping vs billing address.

Groups elements under multiple labels.

<div id="user">User</div>

<div>
  <div id="name">Name</div>
  <input type="text" aria-labelledby="user name"/>
</div>

<div>
  <div id="address">Address</div>
  <input type="text" aria-labelledby="user address"/>
</div>

Describe By

Screen readers read the text within the element given in the attribute aria-describedby="someElement".

Useful for detailed descriptions of effects based on user actions.

Useful for giving instructions to users on correct format for inputing text.

<button aria-label="Close" aria-describedby="description-Close" onclick="myDialogue.close()">X</button>

<div id="description-Close">Closing this window discards information you entered and returns you to main page.</div>

Live Regions

Useful for frequently updated data such as a chat application.

aria-live="" reads updated information

aria-relevant="" defines what updated information to read

-additions -removals -text -all

Live Region Example

Buttons increment or decrement counter by 10.

Adding aria-live="assertive" allows the reader to read the value each time it is incremented or decremented.

HTML

<section>
  <div class="display-panel">
    <div id="count" aria-live="assertive">0</div>
  </div>
  <div class="buttons">
    <button id="inc" class="btn btn-primary">increment</button>
    <button id="dec" class="btn btn-default">decrement</button>
  </div>
</section>

JS

var increment = document.querySelector('#inc');
var decrement = document.querySelector('#dec');
var counter = document.querySelector('#count');

var count = 0;

increment.addEventListener('click',add);
decrement.addEventListener('click',subtract);

function add() {
  count += 10;
  setCounter();
};

function subtract() {
  count -= 10;
  setCounter();
};

function setCounter() {
  counter.innerHTML = count;
}

setCounter();

CSS Selectors

.dropdown[aria-expanded="false"].icon::after {
  content:'rightTriangleicon';
}

.dropdown[aria-expanded="true"].icon::after {
  content:'downTriangleicon';
}

Progressive Enhancement

JS Off

Some users do not enable JS.

To accommodate this user base

Colour

Do not use colour alone in order to convey information.

Use shape , size , contrast in addition to colour.

Motion

Start Animation Button

Include a start animation button to allow users to begin animation.

Seizures

Do not make any page element flash more than 3 times per second.

Customize Animations

For users that have set their devices to reduce animations.

CSS Solution

@media (prefers-reduced-motion: reduce) {
  .animation {animation: none; transition: none;}
}

JS Custom Solution

var motionQuery = matchMedia('(prefers-reduced-motion)');

function handleReducedMotion() {
  if (motionQuery.matches) {
    // adjust animation or transition properties
  }
  else {
    // normal animation
  }
}

motionQuery.addListener(handleReducedMotion);

handleReducedMotion();

Tools

Google

Lighthouse

FireFox

Look for extensions.

Readers

Install a reader to get a sense of what users experience.

Mobile devices and some OSs have built in screen readers.

Testing

Use a testing library.

Test for the desired outcome instead of testing for the code itself.

Linting

Unit Tests

Integration Tests

User Testing

Resources

Website Audit

Maintain a checklist of items to cover when developing a site.

notes navigation

Current URL: /notes/01HTML/02-accessibility/

total notes 36