How to Make your JavaScript Accessible Without Losing Your Sanity (or your Hair)

A presentation at DEVNEXUS in April 2024 in Atlanta, GA, USA by Todd Libby

Slide 1

Slide 1

How to Make JavaScript Accessible Without Losing Your Sanity (or Your Hair) 10-April-2024 • Todd Libby dev.nexus 2024

Slide 2

Slide 2

Thanks!

Slide 3

Slide 3

<html> {.css}

Slide 4

Slide 4

Slide 5

Slide 5

Slide 6

Slide 6

Slide 7

Slide 7

Slide 8

Slide 8

Slide 9

Slide 9

Slide 10

Slide 10

Slide 11

Slide 11

JavaScript

Slide 12

Slide 12

Data The numbers behind the talk

Slide 13

Slide 13

1.2 Billion Page elements tested in 2024 by WebAIM

Slide 14

Slide 14

1173 Up from 1050 elements per home page in 2023

Slide 15

Slide 15

95.9% of home pages had a detected WCAG 2.x failure!

Slide 16

Slide 16

Slide 17

Slide 17

<!DOCTYPE html> <html lang=”en”> <head>

Slide 18

Slide 18

Frameworks and Libraries and JavaScript, oh my!

Slide 19

Slide 19

JavaScript Frameworks Most Improved in Accessibility • Stimulus • Emotion • React • Zone.js • Angular • styled-components • MooTools

Slide 20

Slide 20

JavaScript Libraries Most Improved in Accessibility • YUI • Polyfill • Lodash • AOS • jQuery Mobile • lit-html

Slide 21

Slide 21

Accessible JavaScript You can make it possible! • Keyboard & Mouse • Form validation • Dynamic content • Styling • Performance • Unobtrusive JavaScript

Slide 22

Slide 22

Examples Show me the accessibility!

Slide 23

Slide 23

Keyboard & Mouse

Slide 24

Slide 24

<html> + + const acc = accordion.getElementsByTagName(‘li’); for (var i = 0; i < acc.length; i ) { var accTitle = acc[i].getElementsByTagName(‘h3’); addEvent(accTitle, ‘click’, Acc.clickListener); } < < / JS / < < <ul class=“accordion”> <li> <h3>Todd Libby /h3> <p>Chief Accessibility Officer /p> … More info /li> … /ul>

Slide 25

Slide 25

clickListener: function(event) { var fold = this.parentNode; Acc.expand(fold); preventDefault(event); },

Slide 26

Slide 26

A. B. Make non-keyboard-focusable elements keyboard-accessible. Add an element that is keyboardaccessible (e.g., hyperlink) to the document.

Slide 27

Slide 27

< + < < / / / const acc = accordion.getElementsByTagName(‘li’); for (var i = 0; i < acc.length; i ) { var accLinks = acc[i].getElementsByTagName(‘a’); var accTitleLink = accLinks[0]; addEvent(accTitleLink, ‘click’, Acc.clickListener); } / < <

<ul class=“accordion”> <li id=“position-cao”> <h3><a href=“#cao”>Todd Libby /a> /h3> <p>Chief Accessibility Officer /p> … More info /li> … Other code /ul>

Slide 28

Slide 28

clickListener: function(event) { var fold = this.parentNode.parentNode; Acc.expand(fold); preventDefault(event); },

Slide 29

Slide 29

tabindex=0

Slide 30

Slide 30

<details> • • • • • • • Native HTML Well supported* Supports toggle event Low JS overhead** Accessible Use with <summary> Very customizable

Slide 31

Slide 31

Form Validation

Slide 32

Slide 32

Validating Your Forms ft • Instant validation (field validated on every value change) - NO! • Validating a er the fact (field validated on blur) - Not a big fan • Validation on submission of form (Click and validate) - YES!

Slide 33

Slide 33

form.addEventListener(‘submit’, function(event) { event.preventDefault(); Prevent form submission Prevent custom validation logic const email = document.getElementById(‘email’).value; const password = document.getElementById(‘password’).value; if (!emailIsValid(email)) { alert(‘Password must be between 8-20 characters long’); return; } … / / / Submit the form if validation passes form.submit(); }); / / / const form = document.querySelector(‘form’);

Slide 34

Slide 34

< <

<p aria-live=“assertive” class=“sr-only”> Not a valid email address. /p> <p aria-hidden=“true”> Not a valid email address. /p>

Slide 35

Slide 35

HTMLElement.focus()

Slide 36

Slide 36

Form Accessibility • • • • • • • Inline error messages Place all errors above the form in long forms Clear and concise Do not rely on color alone Focus where important Stop disabling buttons Don’t wrap everything in a <label>

Slide 37

Slide 37

Buttons

Slide 38

Slide 38

<button> <a> <div>

Slide 39

Slide 39

const button = document.createElement(‘div’) button.innerText = ‘Click Here…’

Slide 40

Slide 40

<button>

Slide 41

Slide 41

/ / < < < < < <

<div class=”menu-button-links”> <button type=”button” id=”menubutton” aria-haspopup=”true” aria-controls=”menu2” aria-expanded=”false”> WAI-ARIA Quick Links <svg xmlns=”http: www.w3.org/2000/svg” … /svg> /button> <ul id=”menu2” role=”menu” aria-labelledby=”menubutton”> <li role=”none”> … /li> … <li role=”none”> … /li> /ul> /div>

Slide 42

Slide 42

https://www.w3.org/WAI/content-assets/wai-aria-practices/patterns/menu-button/examples/js/ menu-button-links.js

Slide 43

Slide 43

Styling

Slide 44

Slide 44

Yes! CSS & Accessibility • • • • • • Use semantics and style them accordingly Apply CSS if you have to with setAttribute Do NOT style headings to look like other headings Sensible typography Readability & contrast of text You do not need a framework for everything!

Slide 45

Slide 45

Performance

Slide 46

Slide 46

Performance of JS fi • Consider a simpler solution • Remove unused code • Consider built-in user agent features: • client-side validation • native <video> player • CSS animations • Mini cation, Gzipping, bundlers

Slide 47

Slide 47

Performance of JS fi

  1. HTML is parsed rst. 2. CSS parsed when applicable a. Linked assets start to be fetched. 3. JS is parsed by the browser, evaluates the JS and runs it. 4. The user agent decides how each HTML element should be styled. 5. The result of the styling is painted to the screen.

Slide 48

Slide 48

Unobstrusive JS

Slide 49

Slide 49

Mixing is for cooking and drinks.

Slide 50

Slide 50

Benefits of Unobtrusive JS • • • • • Separation of behaviors from the markup Reusable code Progressive enhancement Graceful degradation Capability detection

Slide 51

Slide 51

< <a id=“alert” href=“javascript:void(0);” onClick=“alert(‘You clicked the button.’);” > Click this super button! /a>

Slide 52

Slide 52

<a id=“alert” href=“#”>Click this button! /a> < <

<script> jQuery(function($) { $(“#alert”).click.function() { alert(“Thanks for clicking the button!”); return false; }); }); /script>

Slide 53

Slide 53

ARIA - Accessible Rich Internet Application

Slide 54

Slide 54

Wrap-up

Slide 55

Slide 55

<

<div role=“button” tabindex=“0” onClick={this.onClick} > Click Here /div>

Slide 56

Slide 56

Slide 57

Slide 57

< <span role=“button” tabindex=“0” onClick={this.onchange} > Super Sleek Button! /span>

Slide 58

Slide 58

document.getElementById(‘hero’).style = ‘font-size: 12rem;’;

Slide 59

Slide 59

Slide 60

Slide 60

Slides: https://bit.ly/4cStCsF 10-April-2024 • Todd Libby dev.nexus 2024

Slide 61

Slide 61

Thank you! 10-April-2024 • Todd Libby dev.nexus 2024