Skip to content

Latest commit

 

History

History
312 lines (277 loc) · 11.8 KB

3.2 Focus.md

File metadata and controls

312 lines (277 loc) · 11.8 KB

Accessibility- FOCUS

Source: Accesibility - Udacity Front End Web Development Nanodegree

2. FOCUS

Table Of Contents:

  • a. FOCUS (MANAGEMENT): What is focus (management)?
  • b. DOM ORDER
  • c. TABINDEX ATTRIBUTE
  • d. SKIP LINKS
  • e. MANAGE FOCUS
  • f. KEYBOARD DESIGN PATTERNS
  • g. OFF-SCREEN CONTENT
  • h. MODALS & KEYBOARD TRAPS

a. DEFINITION: focus (management)

FOCUS= the location on a page that receives input from the keyboard. It shows where keyboard events go in a page.

  • An HTML user interface(UI) consists of multiple interactive widgets (input, buttons & select elements),
  • Such as:form controls, scrollable regions, links, dialog boxes, browser tabs, that form a hierarchy of automatic tab order + built-in keyboard event handling. They are implicitely focussable.
  • Yet, NOT all elements are focussable. Examples are header, paragraphsand images.

FOCUS MANAGEMENT= Move focus around the page using your keyboard to interact with the interface.

  • TAB ORDER: key input is channeled from the system, through a hierarchy of interactive widgets, to the "active(= focused) widget:
  • TAB: move focus forward
  • SHIFT TAB: move focus backwards
  • Arrow keys: to navigate inside a component
Don't add focus to any content a user can Not interact with.

Sources:

b. DOM ORDER

The DOM order matters for FOCUS MANAGEMENT: element.tabIndex;

Tab order = same as DOM order, even if  `visual` order is changed (with CSS).
Changing the  `visual` order can cause confusion among `screen readers` and `keyboard users`, who depend on keyboard navigation. 
  • Work with native elements is good practice for FOCUS behaviour, because they are automatically be inserted into the TAB ORDER, based on their DOM POSITION.
<button> I should </button>
<button> Be Focussed </button>
<button> Last! </button>
  • If Visual order is changed (with CSS), it can cause confusion:
<button style= "float: right;"> 
I should </button>
<button> Be Focussed </button>
<button> Last! </button>
  • To prevent confusion, the Reading and navigation order (code order) SHOULD BE logical and intuïtive.

Sources:

c. TABINDEX ATTRIBUTE

  • Control FOCUS BEHAVIOUR with TABINDEX ATTRIBUTE: element.tabIndex; (tabindex value of an element)
  • NOTE: ONLY NEEDED for Interactional elements (input, buttons & select elements)
  • These elements Must have FOCUS:
    • Header links
    • Call to Action button
    • Search Input
    • Form Elements
    • Footer Links
  • NOT needed for non-interactional elements (HTML-tags, such as: headers, paragraphs or images)
  • These elements should NOT have FOCUS, instead use SEMANTICS:
    • Header
    • Block of text (paragraph)
    • Image
1) tabindex = "-1"

_ [.] NOT in tab order.

  • [.] focus programmatically by focus()
  • [.] Used for Off screen content, that appear in response to a user event() (ex. modals).
HTML: <dialog id="modal" tabindex="-1"></dialog>
JS: document.querySelector(´#modal´).focus()
2) tabindex = "0"
  • [.] to insert Unfocusable element in tab order.
  • [.] focus programmatically by focus()
  • [.] So, keyboard events get directed to it.
HTML: <div id="dropdown" tabindex="0">Settings</div>
JS: document.querySelector(´#modal´).focus()
3) tabindex > 0
  • [.] Jump to the (IN) front of the tab order.

  • [.] If multiple elements, lowest value= first (in tab order).

  • [.] This practice is discouraged and seen as an anti-pattern!

  • NOTE: never remove the focus indicator from an interactive element unless you're going to replace it.

  • Otherwise a keyboard user might not know which element is focused!

Sources:

d. SKIP LINKS

  • Allow screen reader, keyboard, and switch devices users to navigate towards main pagecontent.
  • It bypasses all the following elements before the main content: navigation bar, sublists, sitebars, hamburger menus.
  • Skip links makes all links hidden until focus().
<!--html code-->
<a href="#main-content" class="skip-link">Skip to main content</a>
<nav>
.
.
.
</nav>
<main id="main-content" tabindex="-1">
.
.
.
</main>
/*CSS code*/
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: red;
  color: white;
  padding: 8px;
  z-index: 100;
  }
.skip-link:focus {
  top: 0;
  }

Sources:

e. MANAGE FOCUS

  • To manage Focus in Complex Components, use the WAI-Aria guidelines.
  • The ARIA Authoring Practices ("ARIA Design Patterns doc") provides guidance in selecting which keyboard interaction is appropriate for complex component ("actions", such as drop down menu, tree view component.

f. KEYBOARD DESIGN PATTERNS

  • Use keyboard design patterns to implement focus inside of a component.
  • EXAMPLE: Radio patternImplement Keyboard Event Listeners
  • Use ROVING FOCUS( "roving tabindex") to make changes in: radiogroup.jsfile.
  • first radio button:
  1. tabindex="0"
  2. checked
  3. focus()
<li tabindex="0" checked> //set tab index to 0 on the currently active item
<li tabindex="-1"> //set tab index to -1 for all children
<li tabindex="-1">
<li tabindex="-1">
<li tabindex="-1">
  • The component uses a keyboard event listener to know which keyboard the user pressed.
  • to know on which component to set next tabindex to 0
  • when moving to the next element => first element:
  1. tabindex="-1"
  2. remove checked
  3. unfocus ::
<li tabindex="-1"> //change tabindex to -1, remove checked
<li tabindex="0"> checked //add focus(), later remove focus() and add checked
<li tabindex="-1">
<li tabindex="-1">
<li tabindex="-1">

Next element: 1. tabindex="0" / 2. checked / 3. focus()

  • If last element tab move to first element.
  • If first element shift + tab move to last element.

Sources:

g. OFF-SCREEN CONTENT

  • A drawer panel can lead focus to visually disappear.
  • Overcome it by setting display: none; or visibility: hidden;

####How to check if OFF-SCREEN CONTENT is ACCESSIBLE?

  1. Track focus: to find missing focus, type into console: document.activeElement;
    • this gives a reference to the current focussed item
  2. Use the Chrome Accessibility Developer Tools Extension to quickly find accessibility issues in your page:
    • to add an Accessibility Properties panel to Elements inspector
    • to add an Accessibility option to audits panel.

Sources:

h. KEYBOARD TRAP & MODAL

  • KEYBOARD TRAP: keyboard focus is locked or trapped at one particular page element.
  • The user CAN NOT navigate to and from all navigable page elements, using only a keyboard.
  • Prevent a permanent keyboard trap.

EXCEPTION: use a temporary keyboard trap for a MODAL

  • Use WebAim in Modals to trap keyboard focus inside the modal until modal is closed.
  • It => return focus to last focused element before modal open. HTML:
<button class="modal toggle"> Open Modal </button>

<div class="modal">
  <h1> Join our newsletter </h1>
  <p> short description about the newsletter & why to join? 
  </p>
  <div class="field">
  <label for="fullname"> Full Name </label>
  <input id="fullname" type= "text">
</div>
 <div class="field">
  <label for="email"> E-mail address </label>
  <input id="email" type= "text">
</div>
<button id="signup"> Sign me up!</button>
</div>

<div class="modal overlay"></div>

JAVASCRIPT:

//hold previosly focussed element
let focusedElementBeforeModal;

//find the modal and its overlay
const modal document.querySelector(´modal´);
const modalOverlay document.querySelector(´modalOverlay´);

//add EventListener "click" on ModalToggle to openModal
let modalToggle document.querySelector(´modalToggle´);
modalToggle.addEventListener(´click´, openModal);

//create function openModal
function openModal(){
//save current focus
focusedElementBeforeModal= document.activeElement;

//Listen for and trap the keyword
modal.addEventListener(´keydown´, trapTabKey);

//Listen to indicators to close the modal
modalOverlay.addEventListener(´click´, closeModal);
//Sign-up button
let signupBtn.addEventListener(´click´, closeModal);

//Find all focusable children
const focusableElementString = ´a[href], area[href],
input:not([disabled]), select:not([disabled]),
textarea:not([disabled]), button:not([disabled]), iframe, object,
embed, [tabindex=´0´]), [contenteditable]´;

let focusableElements = 
modal.querySelectorAll(´focusableElementString´);

//Convert Nodelist to Array
focusableElements= Array.prototype.slice.call(focusableElements);

//Figure out first and last element in group of focusableElements
let firstTabStop = focusableElements[0];
let secondTabStop = focusableElements[focusableElements.length -1];

//Show the modal and overlay
modal.style.display = ´block´;
modalOverlay.style.display = ´block´;

//Focus firstTabStop
firstTabStop.focus();

function TapKeyPress()
//Check for TapKeyPress
if (e.keyCode === 9) {

//shift + TAB
if (e.shiftKey) {
if document.activeElement=== firstTabStop) {
e.preventDefault();
lastTabStop.focus();
}
//TAB
} else {
if document.activeElement=== lastTabStop) {
e.preventDefault();
firstTabStop.focus();
    }
  }
}

//Escape
if (e.keyCode ===27) {
closeModal();
    }
  }
}

function closeModal(){
//Hide the Modal and Overlay
modal.style.display = ´none´;
modalOverlay.style.display = ´none´;
  
//Set focus back to element before modalOpen
focusedElementBeforeModal.focus();
}

Sources: