CSS, JavaScript, & Accessibility

A presentation at An Event Apart Spring Summit in April 2022 in by Ire Aderinokun

Slide 1

Slide 1

CSS, JavaScript, & Accessibility Ire Aderinokun @ An Event Apart Spring Summit 2022

Slide 2

Slide 2

“By default, HTML is accessible. Web accessibility involves ensuring that content remains accessible.” https://developer.mozilla.org/en-US/docs/Learn/Accessibility

Slide 3

Slide 3

Web accessibility is the inclusive practice of ensuring there are no barriers that prevent access to websites

Slide 4

Slide 4

Physical disabilities

Slide 5

Slide 5

Situational disabilities

Slide 6

Slide 6

Socio-economic restrictions

Slide 7

Slide 7

Accessibility is about inclusion

Slide 8

Slide 8

Slide 9

Slide 9

  1. Content must be perceivable 🧏

Slide 10

Slide 10

  1. Interface must be operable 🛠

Slide 11

Slide 11

  1. Content must be understandable 📖

Slide 12

Slide 12

  1. Code must be robust ⚙

Slide 13

Slide 13

“By default, HTML is accessible, if used correctly. Web accessibility involves ensuring that content remains accessible.” https://developer.mozilla.org/en-US/docs/Learn/Accessibility

Slide 14

Slide 14

With HTML, WYSIWYG

Slide 15

Slide 15

<main> <h1>Page Heading</h1> <p>Other less important text</p> </main>

Slide 16

Slide 16

In the absence of other languages, we have to use HTML correctly

Slide 17

Slide 17

https://ireade.github.io/motherduckingwebsite/

Slide 18

Slide 18

https://ireade.github.io/motherduckingwebsite/

Slide 19

Slide 19

By default, HTML is perceivable 🧏

Slide 20

Slide 20

Guideline 1.3 — Create content that can be presented in different ways ✅

Slide 21

Slide 21

Guideline 1.4 — Make it easier for users to see and hear content including separating foreground from background ✅

Slide 22

Slide 22

By default, HTML is operable 🛠

Slide 23

Slide 23

Guideline 2.1 — Make all functionality available from a keyboard ✅ Guideline 2.5 — Make it easier for users to operate functionality through various inputs beyond keyboard ✅

Slide 24

Slide 24

By default, HTML is understandable 📖

Slide 25

Slide 25

Guideline 3.2 — Make Web pages appear and operate in predictable ways ✅

Slide 26

Slide 26

Guideline 3.3 — Help users avoid and correct mistakes ✅

Slide 27

Slide 27

By default, HTML is robust ⚙

Slide 28

Slide 28

By default, HTML is robust, if used correctly ✅

Slide 29

Slide 29

HTML can be inaccessible

Slide 30

Slide 30

Missing text alternatives ☹ <img src=“link/to/really-important-image.png”

Slide 31

Slide 31

Using the wrong elements ☹

<p>Enter your username:</p> <input type=“text”>

Slide 32

Slide 32

Weird tab order ☹

<ul> <li><a href=“/one” tabindex=“2”>Link One</a></li> <li><a href=“/two” tabindex=“3”>Link Two</a></li> <li><a href=“/three” tabindex=“1”>Link Three</a></li> </ul>

Slide 33

Slide 33

HTML

Slide 34

Slide 34

JavaScript CSS

Slide 35

Slide 35

Adding content with CSS ☹

<div id=“important”></div> #important after { content: “Really important information that everyone should know” : : }

Slide 36

Slide 36

Altering element behaviour with JavaScript ☹

<div onClick=“goToPage(‘/about’)”> About Us </div>

Slide 37

Slide 37

90% of accessibility is about using HTML correctly. The other 10% is about not using CSS/JS incorrectly.

Slide 38

Slide 38

CSS, JavaScript, & Accessibility

Slide 39

Slide 39

Part One CSS & Accessibility

Slide 40

Slide 40

CSS is used to describe the presentation of an HTML document

Slide 41

Slide 41

Slide 42

Slide 42

Slide 43

Slide 43

DOM <head> <title>Understanding the Critical Rendering Path</title> <link rel=”stylesheet” href=”style.css”> </head> <body> <header> <h1>Understanding the Critical Rendering Path</h1> </header> <main> <h2>Introduction</h2> <p>Lorem ipsum dolor sit amet</p> </main> <footer><small>Copyright 2017</small></footer> </body>

Slide 44

Slide 44

CSSOM body { font-size: 18px; } header { color: plum; } h1 { font-size: 28px; } main { color: firebrick; } h2 { font-size: 20px; } footer { display: none; }

Slide 45

Slide 45

DOM + CSSOM - Non-visible elements = Render tree

Slide 46

Slide 46

Slide 47

Slide 47

Slide 48

Slide 48

AOM <form> <p>Make a choice:</p> <input type=“radio” name=“choice” id=“yes” /> <label>Yes</label> <input type=“radio” name=“choice” id=“no” /> <label>No</label> <input type=“checkbox” name=“agree” id=“agree” /> <label>I agree</label> </form>

Slide 49

Slide 49

Slide 50

Slide 50

Slide 51

Slide 51

#1 Don’t use CSS to convey meaning or content

Slide 52

Slide 52

h1 after { content: “My Page Title” : : }

Slide 53

Slide 53

https://tink.uk/accessibility-support-for-css-generated-content/

Slide 54

Slide 54

“In other words, use CSS generated content to change or supplement the design, but not to create or alter important content on the page.” — Léonie Watson https://tink.uk/accessibility-support-for-css-generated-content/

Slide 55

Slide 55

❌ ✅ .element after { content: .element any content content: “” / * * / : : : } : } after {

Slide 56

Slide 56

<input class=“error” > <input class=“success” > .error { border-color: red; } .success { border-color: green; }

Slide 57

Slide 57

<p>Price:</p> <span class=“strike”>$50</span> <span>$5,000</span> .strike { text-decoration: line-through; }

Slide 58

Slide 58

#2 Don’t use CSS to change the semantics of HTML

Slide 59

Slide 59

❌ ✅ This is <span class=“emphasise”>really</span> important .emphasise { font-style: italic; } This is <em>really</em> important

Slide 60

Slide 60

Slide 61

Slide 61

display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅

Slide 62

Slide 62

display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅

Slide 63

Slide 63

display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅

Slide 64

Slide 64

https://frend.co/components/tabs/

Slide 65

Slide 65

display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅

Slide 66

Slide 66

display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅

Slide 67

Slide 67

<div>Element #1</div> <div style=“visibility:hidden;”> Element #2 </div> <div>Element #3</div>

Slide 68

Slide 68

Don’t use visibility: hidden;

Slide 69

Slide 69

display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅

Slide 70

Slide 70

display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅

Slide 71

Slide 71

Slide 72

Slide 72

Source order Visual order

<body> body { display: flex } <footer>…</footer> header { order: 1 } <nav>…</nav> nav { order: 2 } <header>…</header> main { order: 3 } <main>…</main> footer { order: 4 } </body>

Slide 73

Slide 73

“With this power comes great responsibility” — Rachel Andrew https://rachelandrew.co.uk/archives/2015/07/28/modern-css-layout-power-and-responsibility/

Slide 74

Slide 74

#3 Don’t write CSS that undoes the default accessible styles

Slide 75

Slide 75

Browser CSS

Slide 76

Slide 76

✅ Text & element sizes ✅ Colours & contrast ✅ Hover, focus, & active states

Slide 77

Slide 77

My CSS Browser CSS

Slide 78

Slide 78

button { font-size: 6px; }

Slide 79

Slide 79

button { color: lightgray; }

Slide 80

Slide 80

https://uxplanet.org/active-hover-and-focus-states-for-designers-d789531fe767

Slide 81

Slide 81

https://bitsofco.de/when-do-the-hover-focus-and-active-pseudo-classes-apply/

Slide 82

Slide 82

:active then :focus then :hover ❌ :hover then :focus then :active ✅ button:active { background-color: green; } button:hover { background-color: red; } button:focus { background-color: blue; } button:focus { background-color: blue; } button:hover { background-color: red; } button:active { background-color: green; }

Slide 83

Slide 83

Slide 84

Slide 84

❌ ✅ :focus { :focus { outline: none; outline: none; other focus styles } / * * / }

Slide 85

Slide 85

button:focus:not(:focus-visible) { outline: none; } button:focus-visible { background-color: darksalmon; }

Slide 86

Slide 86

Write custom CSS cautiously

Slide 87

Slide 87

Slide 88

Slide 88

#4 Do use CSS to improve on the default accessible styles

Slide 89

Slide 89

Guideline 1.4.8 — Visual presentation

  1. Text blocks should be no wider than 80 characters, for maximum readability. 2. Line height should be at least 1.5 times the text size within paragraphs, and at least 2.25 times the text size between paragraphs.

Slide 90

Slide 90

The default browser styling doesn’t meet these requirements

Slide 91

Slide 91

p { line-height: 1.5; padding: 2.25rem; max-width: 80ch; }

Slide 92

Slide 92

Guideline 2.4.1 — Bypass blocks A mechanism should be provided that allows the user to skip straight to the main content or functionality available on the page, past the repeated features (such as the company logo or navigation).

Slide 93

Slide 93

<body> #skip-link { <a id=”skip-link” href=”#main”> position: absolute; Skip to content transform: translateY(-100%); </a> } <!— navigation, etc. #skip-link:focus { transform: translateY(0%); <main id=“main”> } > - </body>

Slide 94

Slide 94

Guideline 2.4.1 — Bypass blocks A mechanism should be provided that allows the user to skip straight to the main content or functionality available on the page, past the repeated features (such as the company logo or navigation). … If a proper structure of headings and semantic containers is provided to navigate with (for example <section>, <aside>, etc.), then an added “skip link” is not needed.

Slide 95

Slide 95

#5 Do adapt CSS to device capabilities

Slide 96

Slide 96

CSS

Slide 97

Slide 97

.element { -webkit-transition: all 4s ease; -moz-transition: all 4s ease; -ms-transition: all 4s ease; -o-transition: all 4s ease; transition: all 4s ease; }

Slide 98

Slide 98

.element { color: #000; color: var(—text-color); }

Slide 99

Slide 99

@supports ( declaration ) { Feature-based CSS here / * * / }

Slide 100

Slide 100

Legacy code Modern code @supports (display: grid) { main { main { display: table; display: grid; } } }

Slide 101

Slide 101

#6 Do adapt CSS to user preferences

Slide 102

Slide 102

https://dbaron.org/css/user/

Slide 103

Slide 103

https://codereview.chromium.org/64843004

Slide 104

Slide 104

“All users, including users with disabilities, [should] have equal control over the environment they use to access the web” https://www.w3.org/TR/UAAG20

Slide 105

Slide 105

@media ( prefers-* ) { Preference-based CSS here / * * / }

Slide 106

Slide 106

Adapt to data preferences .element { background-image: url(“highest-quality.png”); } @media ( prefers-reduced-data: reduce ) { .element { background-image: url(“smaller-size.jpg”); } }

Slide 107

Slide 107

Adapt to data preferences prefers-reduced-data Adapt to motion preferences prefers-reduced-motion Adapt to colour preferences prefers-color-scheme Adapt to contrast preferences prefers-contrast Adapt to trasparency preferences prefers-reduced-transparency

Slide 108

Slide 108

Giving users control

Slide 109

Slide 109

CSS & Accessibility 1. Don’t use CSS to convey meaning or content

  1. Do use CSS to improve on the default accessible styles
  2. Don’t use CSS to change the semantics of HTML 3. Don’t write CSS that undoes the default accessible styles
  3. Do adapt CSS to device capabilities 3. Do adapt CSS to user preferences

Slide 110

Slide 110

Part Two JavaScript & Accessibility

Slide 111

Slide 111

JavaScript is used to make web pages more interactive

Slide 112

Slide 112

<a> <details> <form> <summary> <input> <button> <select> <textarea> <option> <progress>

Slide 113

Slide 113

Slide 114

Slide 114

#1 Don’t use JavaScript for functionality HTML provides

Slide 115

Slide 115

✅ Triggered by mouse, enter key, and space bar ✅ Focusable via the keyboard and other input devices ✅ Accessible name and state provided to assistive tech

Slide 116

Slide 116

<button>Do something</button>

Slide 117

Slide 117

<div onClick=“doSomething(e)”> Do something </div>

Slide 118

Slide 118

Extra work 😓 <div tabindex=“0” role=“button” onKeyPress=“handleBtnKeyPress(e)” onClick=“doSomething(e)”> Do something </div>

Slide 119

Slide 119

More extra work 😰 <div tabindex=“0” function handleBtnKeyPress(e) { role=“button” if ( e.keyCode 32 || e.keyCode 13) { onKeyPress=“handleBtnKeyPress(e)” onClick=“doSomething(e)”> doSomething(e); Do something }

</div> = = = = = = }

Slide 120

Slide 120

Even more extra work 🥵 <div tabindex=“0” role=“button” onKeyPress=“handleBtnKeyPress(e)” onClick=“doSomething(e)” aria-pressed=”false”> Toggle </div>

Slide 121

Slide 121

Slide 122

Slide 122

✅ ❌ <button onClick=“goToPage(‘/about’)”> <a href=“/about”>About Us</a> About Us </button>

Slide 123

Slide 123

<button onClick=“goToPage(‘/about’)”> About Us </button> function goToPage(url) { // Do some other things window.location.href = url; }

Slide 124

Slide 124

Keep JavaScript enhancements unobtrusive

Slide 125

Slide 125

<a href=“/about” onClick=“goToPage(event, ’/about’)”> About Us </a> function goToPage(event, url) { event.preventDefault(); // Do some other things window.location.href = url; }

Slide 126

Slide 126

<a href=“/about” onClick=“goToPage(e, ’/about’)”> About Us </a> function goToPage(e, url) { e.preventDefault(); // Do some other things window.location.href = url; }

Slide 127

Slide 127

event.preventDefault() is the 🔑

Slide 128

Slide 128

#2 Where possible, don’t require JavaScript for critical features

Slide 129

Slide 129

Slide 130

Slide 130

Without JS With JS

Slide 131

Slide 131

“While WCAG 1.0 from 1999 required that pages be functional and accessible with scripting disabled, WCAG 2 and all other modern guidelines allow you to require JavaScript” https://webaim.org/techniques/javascript/

Slide 132

Slide 132

Different groups have different access needs

Slide 133

Slide 133

People with physical disabilities are more likely to rely on JS Only 0.07% of screen reader users have JavaScript disabled. The global average is 1%.

Slide 134

Slide 134

People with socio-economic restrictions are more likely to avoid JS Over 50% of the Sudanese mobile browsing is with Opera Mini

Slide 135

Slide 135

Average File Sizes 430 KB 27 KB HTML 66 KB CSS https://almanac.httparchive.org/en/2021/page-weight JS

Slide 136

Slide 136

Slide 137

Slide 137

JavaScript-disabled experience JavaScript-enabled experience

Slide 138

Slide 138

JavaScript-enabled experience JavaScript-disabled experience

Slide 139

Slide 139

JavaScript-disabled experience JavaScript-enabled experience

Slide 140

Slide 140

“Just because JavaScript is used on a page does not mean that the page is inaccessible. In many cases, JavaScript can be used to greatly improve accessibility and optimize the user experience.” https://webaim.org/techniques/javascript/

Slide 141

Slide 141

“Just because JavaScript is used on a page does not mean that the page is inaccessible. In many cases, JavaScript can be used to greatly improve accessibility and optimize the user experience.” https://webaim.org/techniques/javascript/

Slide 142

Slide 142

#3 Do use JavaScript to improve on the default accessible behaviour

Slide 143

Slide 143

Slide 144

Slide 144

Guideline 3.3.3 — When an error is detected and suggestions for correction are known, provide these to the user

Slide 145

Slide 145

Slide 146

Slide 146

Some HTML elements aren’t accessible enough, yet ☹

Slide 147

Slide 147

Problems with <video> ❌ Controls not focusable via keyboard ❌ Can’t pause/play video using space key ❌ No arrow key support for scrubber & more

Slide 148

Slide 148

“Modern browsers provide a default media player. Most have limited functionality to support accessibility.” https://www.w3.org/WAI/media/av/player/

Slide 149

Slide 149

https://www.digitala11y.com/accessible-jquery-html5-media-players/

Slide 150

Slide 150

Problems with <canvas> ❌ Content not in the DOM & AOM ❌ No “proper” text alternatives ❌ “Elements” not focusable & more

Slide 151

Slide 151

Sometimes, we need JavaScript

Slide 152

Slide 152

#4 Do use JavaScript to create components that don’t exist

Slide 153

Slide 153

Slide 154

Slide 154

<tooltip> <dropdown> <carousel> <tab-group> <toggle> <card> <social-button> <accordion> <loading> <tab>

Slide 155

Slide 155

https://www.w3.org/TR/2021/NOTE-wai-aria-practices-1.2-20211129/examples/carousel/carousel-1-prev-next.html

Slide 156

Slide 156

Guidelines related to carousels 1.3.1 — Information, structure, and relationships conveyed through presentation can be programmatically determined 2.1.1 — All functionality should be accessible using keyboard controls 2.2.2 — Controls should be provided to pause, stop, or hide moving content 4.1.2 — The name and role of user interface components (e.g. form inputs, buttons, links, etc.) should be programmatically determinable

Slide 157

Slide 157

<ul id=”slides”> <li> Slide One </li> <li> Slide Two </li> <li> Slide Three / * / / * * * * * / / / </ul> </li>

Slide 158

Slide 158

<section> <div> <button>Toggle Play Slideshow</button> <button>Previous Slide</button> <button>Next Slide</button> </div> <ul id=”slides”> <li> … </li> </ul> </section>

Slide 159

Slide 159

<section> <div> <button>Toggle Play Slideshow</button> <button>Previous Slide</button> <button>Next Slide</button> </div> <ul id=”slides”> <li> … </li> </ul> </section>

Slide 160

Slide 160

<section> <div> <button>Toggle Play Slideshow</button> <button>Previous Slide</button> <button>Next Slide</button> </div> <ul id=”slides”> <li> … </li> </ul> </section>

Slide 161

Slide 161

<section aria-roledescription=”carousel” aria-label=“Slideshow”> <div> <button>Toggle Play Slideshow</button> <button aria-controls=”slides”>Previous Slide</button> <button aria-controls=”slides”>Next Slide</button> </div> <ul id=”slides”> <li role=”group” aria-roledescription=”slide” aria-label=”1 of 3”> … </li> </ul> </section>

Slide 162

Slide 162

Write custom components cautiously

Slide 163

Slide 163

https://www.w3.org/TR/2021/NOTE-wai-aria-practices-1.2-20211129/examples/

Slide 164

Slide 164

https://frend.co/

Slide 165

Slide 165

https://inclusive-components.design/

Slide 166

Slide 166

JavaScript & Accessibility 1. Don’t use JavaScript for functionality HTML provides 2. Where possible, don’t require JavaScript for critical features

  1. Do use JavaScript to improve on the default accessible behaviour 2. Do use JavaScript to create components that don’t exist

Slide 167

Slide 167

“By default, HTML is accessible, if used correctly. Web accessibility involves ensuring that content remains accessible.” https://developer.mozilla.org/en-US/docs/Learn/Accessibility

Slide 168

Slide 168

“So next time someone tells you to make things accessible, tell them that instead you don’t intend to make it inaccessible in the rst place.” — George Kemp fi https://dev.to/gkemp94/the-web-is-accessible-by-default-stop-breaking-it-4cg4

Slide 169

Slide 169

Thank you! Ire Aderinokun 🇳🇬 COO & VP Engineering of Helicarrier Google Web Expert ireaderinokun.com bitsofco.de @ireaderinokun