Keyboard
Many users with motor disabilities rely on the keyboard as well as many blind users. For many enterprise applications efficiency may be the reason to use the keyboard. As an Ionic application can target the web its important to test for keyboard accessibility.
The first step in testing keyboard accessibility is to pressing the Tab key to see what interactive elements you can and cannot reach.
Testing can be done in any web browser or mobile device with a bluetooth keyboard.
You may need to enable tabbing to ensure all interactive controls will focus:
- For Mac - Visit
System Preferences
>Keyboard
>Shortcuts
>Keyboard
. - For Safari - Visit
Safari
>Preferences
>Advanced
and check the boxPress Tab to highlight each item on a webpage
Hidden Controls
If you paste the following line in your dev tools console you can see whenever the active control changes and it will reveal controls that are focused but hidden:
document.body.addEventListener('focusin', () => console.log(document.activeElement));
Tips
- Setting
opacity
tonone
orheight
/width
to0
is often used to hide elements but they are still focusable with the keyboard. Usedisplay: none
to truly hide elements. - A typical cause for hidden controls is the css
outline
set tonone
or0
. Consider custom styling outlines instead. - The
div
element is not focusable. If adiv
has interactivity then it needs to be fixed (eg by changing tobutton
and changing the style). - Test using arrow keys as well as the tab key. Not every element accessible via tab can be accessed via arrow keys (and should be).
You can override default styling for a button
when you replace a div
. For example:
background-color: transparent;
border: none;
border-radius: 0;
Testing Escape
Pressing the Esc
key on the keyboard will close Ionic components like an alertController
, ion-picker
, ion-menu
etc. Make sure to test by pressing Esc
on elements you have written and handle by using the keyup
event and also be sure to focus()
where the user should navigate from next.
Ionic Component Styling
You can add css styling to Ionic components so that during keyboard navigation the focused element is easily visible. For example, this css will show a red border around any element:
ion-input.has-focus,
button:focus-visible,
ion-button.ion-focused,
ion-segment-button.ion-focused,
ion-radio.ion-focused,
ion-select.ion-focused,
ion-fab.ion-focused,
ion-searchbar.ion-focused,
ion-checkbox.ion-focused,
ion-toggle.ion-focused,
ion-range.ion-focused,
ion-datetime.ion-focused,
ion-accordion.ion-focused,
ion-textarea.ion-focused {
outline: 2px solid red;
}
For the above css to work there are some components you will need to add class="ion-focusable"
to. This includes: ion-fab
, ion-searchbar
, ion-checkbox
,
ion-toggle
, ion-range
, ion-datetime
, ion-accordion
, and ion-textarea
. For example:
<ion-textarea class="ion-focusable"></ion-textarea>
tip
One important difference between using a psuedoclass like ion-focused
and focus
is that focus
will style the element whether the user focused it through keyboard or by clicking on it. Using ion-focused
will mean that the element is only styled when it is focused via the keyboard.
Non-interactive Components
Some components like ion-badge
are not interactive but you may want to make them interactive by allowing a user to click on them. Example:
<ion-badge (click)="dostuff()">33</ion-badge>
But, this component cannot be reached through keyboard interaction. So it is better to refactor this to:
<button (click)="dostuff()"><ion-badge>33</ion-badge></button>
You will need to style using focus-visible
for the focus area to be visible:
button:focus-visible {
outline: 2px solid red;
}
Focusing Non-interactive Elements
If you have a non-interactive element like a div
or span
you can focus it by using the focus()
method. However, because these elements are not interactive a screen reader will not read the element and the focus will not change.
You can set tabindex="0"
on the element to allow it to focus.
<span tabindex="0" #container class="error"> {{ errorMessage }} </span>
You could also set role="button"
however, in general it is not a good idea to make non-interactive elements focusable as it interrupts the natural flow of interactive elements, so use this technique sparingly.