Making Single Page Apps Accessible jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
A presentation at NDC Sydney 2024 in February 2024 in Sydney NSW, Australia by Jess Budd
Making Single Page Apps Accessible jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
JESS BUDD - Senior software engineer - Web accessibility nerd - Lover of lego jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
TIM BERNERS-LEE Inventor of the World Wide Web jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
The power of the web is in its universality. Access by everyone, regardless of disability is an essential aspect. - Tim Berners-Lee jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
It doesn’t have to be this way. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Nothing in React prevents us from building accessible web apps - Leslie Cohn-Wein, Netlify jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
… @jessbudd4 jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Low hanging does not mean low impact. - Samuel Proulx, Accessibility Evangelist, blind since birth jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
What is accessibility?
Removing barriers to using your website @jessbudd4 jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Accessibility benefits all of us. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Image credit: Microsoft Inclusive Design jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Accessibility: otherwise known as A11y jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Visual •285 million worldwide •Blindness •Colour blindness •Low or tunnel vision jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Auditory •1 in 6 Australians •Profound deafness •Hard of hearing jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Motor •Loss of limbs •Chronic pain conditions •Cerebral Palsy jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Cognitive •Intellectual impairments •Learning disabilities •Dementia jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Be kind to your future (old) self. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Web Content Accessibility Guidelines
WCAG (wuh-cag) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG (wuh-cag) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Perceivable Operable Understandable Robust jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
• Level A: bare minimum • Level AA: industry standard to aim for • Level AAA: highest standard jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
HTML
Use native browser elements and controls jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Why does it matter? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Image credit: Microsoft Inclusive Design jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Accessibility is good for SEO jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
If a screen reader can’t understand your content, neither can Google. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// Inaccessible card component <template> <div class=”card”> <div>{{productName}}</div> <div>{{productDescription}}</div> <div v-on:click=”doSomething”> {{buttonText}} </div> </div> </template> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Click to edit jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
<CustomComponent> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// More accessible card component <template> <li :class=”card”> <h2>{{productName}}</h2> <p>{{productDescription}}</p> <button v-on:click=”doSomething”> {{buttonText}} </button> </li> </template> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Divs are not buttons. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
<button v-on:click={handleClick}> {{buttonText}} </button> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Give buttons some love jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG success criteria: 1.3.1 - Info and relationships (A) 2.1.1 - Keyboard (A) 4.1.2 - Name, Role, Value (A) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
FORMS
Inputs must have labels. Labels must be linked. jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// label not linked to input <label> Lego character: </label> <input type=”text” K N A L B , t x e Edit t name=”character” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// explicitly linked label to input <label for=”uniqueId”> Lego character: </label> <input id=”uniqueId” R E T C A R A H C O Edit text, LEG type=”text” name=”character” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
How can I make sure my IDs are unique? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
import { v4 as uuid } from “uuid”; <script> data() { return { id: ${this.name}-${uuid()}
} } }; </script> <template> <div class=”a11y-input”> <label v-bind:for=”uniqueId”>{{ label }}</label> <input v-bind:id=”uniqueId” v-bind:name=”name” type=”text” /> </div> </template> jessbudd@bsky.social
jessbudd@front-end.social
jessbudd44
@jessbudd
@jessbudd4
import { v4 as uuid } from “uuid”; <script> data() { return { id: ${this.name}-${uuid()}
} } }; </script> <template> <div class=”a11y-input”> <label v-bind:for=”uniqueId”>{{ label }}</label> <input v-bind:id=”uniqueId” v-bind:name=”name” type=”text” /> </div> </template> jessbudd@bsky.social
jessbudd@front-end.social
jessbudd44
@jessbudd
@jessbudd4
import { v4 as uuid } from “uuid”; <script> data() { return { id: ${this.name}-${uuid()}
} } }; </script> <template> <div class=“a11y-input”> <label v-bind:for=”uniqueId”>{{ label }}</label> <input v-bind:id=”uniqueId” v-bind:name=”name” type=”text” /> </div> </template> jessbudd@bsky.social
jessbudd@front-end.social
jessbudd44
@jessbudd
@jessbudd4
Implicit linking? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// implicitly linked label to input <label> Lego character: <input type=”text” name=”character” R E T C A R A H C O Edit text, LEG /> </label> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
What if the design doesn’t have labels? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// label hidden with css is still announced <label class=”sr-only” for=”legoCharacter”> Lego character: </label> <input id=”legoCharacter” type=”text” name=”character” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// visually hidden, but accessible to screen readers .sr-only { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; width: 1px; overflow: hidden; position: absolute; white-space: nowrap; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG success criteria: 3.3.2 - Labels or instructions (A) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Can I use placeholders instead? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Placeholders are not labels jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
…or suitable help text jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG success criteria: 3.3.2 - Labels or instructions (A) 3.3.5 - Help (AAA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
… jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Implicitly linked touch target jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Explicitly linked touch target jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG success criteria: 2.5.8 - Target size (minimum) (AA) 2.5.5 - Target size (AAA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Autocomplete jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
<label for=”uniqueId”> First name: </label> <input id=”uniqueId” type=”text” name=”firstName” autocomplete=”given-name” /> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG success criteria: 1.3.5 - Identify input purpose (AA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
FOCUS STYLES
Image credit:Access Guide jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Safari: Firefox: Chrome: jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Removing the focus outline is like removing the wheelchair ramp from a school because it doesn’t fit the aesthetic. - David Gilbertson jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Meme where am I jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Screen shot of page with masses of ??? links and question marks jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
/* don’t just remove */ :focus { outline: none; } / replace with something! */ :focus-visible { / branded focus styles here */ outline: 2px dotted #10ffc3; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG success criteria: 1.4.11 - Non-text contrast (AA) 2.4.7 - Focus visible (AA) 2.4.13 - Focus appearance (AAA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Make it big and stand out jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Outlines are best jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Offset outlines even better *:focus-visible { outline: 2px dotted #10ffc3; outline-offset: 2px; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
ROUTING
Traditional multi-page app behaviour Builds the page jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Single page app behaviour Builds the page jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
PAGE TITLES
PAGE TITLE jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
LEGO IS FUN!
<head> MY FAVE LEGO MORE LEGO <meta charset=”utf-8”> <title>Lego is fun!</title> <link rel=”stylesheet” href=”style.css”> </head> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// react functional component import { useEffect } from “react” export const BlogPost = () =>{ useEffect(() => { document.title = “Trolls lego is the best” }) return( <> <h1>A heading</h1> <p>Some page content</p> </> ) } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// vue page level component <script> export default { name: “Blog post”, mounted() { document.title = “Trolls lego is the best”; }, }; </script> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
const router = new VueRouter({ routes: [ { path: ‘/blog’, component: BlogComponent, meta: { title: “My awesome Lego blog” } }, { path: ‘/about’, component: AboutComponent, meta: { title: “About Lego Lover” } } ] }); jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
router.beforeEach((to, from, next) => { document.title = to.meta.title || ‘${defaultTitle}’; next(); }); jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// use helmet to update additional meta data at the same time import {Helmet} from “react-helmet”; export const SignupForm = () =>{ return( react-helmet <Helmet> <title>{meta.title}</title> <meta name=”image” content={meta.image} /> <meta name=”description” content={meta.description}/> <meta name=”og:title” content={meta.title}/> <meta name=”og:description” content={meta.description}/> <meta name=”og:image” content={meta.image}/> </Helmet> vue-meta ) } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Click to edit jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
WCAG success criteria: 2.4.2 - Page titled (A) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
FOCUS MANAGEMENT
Option 1: Fake a traditional navigation jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Option 2: Optimise navigation jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Tabindex tabindex=”0” // makes element focusable in tab/DOM order tabindex=”-1” // makes elements focusable only via scripting tabindex=”5” // danger Will Robinson! jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
import React, { useEffect, useRef } from ‘react’; const PageComponent = () => { const h1Ref = useRef(null); useEffect(() => { if (h1Ref.current) { h1Ref.current.focus(); } }, []); return ( <h1 ref={h1Ref} tabIndex=”-1”>Lego is the best!</h1> // Rest of the component ); }; jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
import React, { useEffect, useRef } from ‘react’; const PageComponent = () => { const h1Ref = useRef(null); useEffect(() => { if (h1Ref.current) { h1Ref.current.focus(); } }, []); return ( <h1 ref={h1Ref} tabIndex=”-1”>Lego is the best!</h1> // Rest of the component ); }; jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
import React, { useEffect, useRef } from ‘react’; const PageComponent = () => { const h1Ref = useRef(null); useEffect(() => { if (h1Ref.current) { h1Ref.current.focus(); } }, []); return ( <h1 ref={h1Ref} tabIndex=”-1”>Lego is the best!</h1> // Rest of the component ); }; jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// don’t show focus for headings H1:focus-visible { outline: none; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
MODALS
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Modals are actually the boss battle at the end of web accessibility. - Rob Dodson, host of A11yCasts jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
// send focus to non-destructive button <dialog> <h2>Delete Conversation</h2> <p>Are you sure you want to delete this conversation? This action cannot be undone.</p> <button>{{destructiveAction}}</button> <button autofocus>{{cancel}}</button> </dialog> jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
:modal { border: 5px solid red; background-color: yellow; box-shadow: 3px 3px 10px rgb(0 0 0 / 50%); } ::backdrop { background: rebeccapurple; opacity: 0.75; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
:modal { border: 5px solid red; background-color: yellow; box-shadow: 3px 3px 10px rgb(0 0 0 / 50%); } ::backdrop { background: rebeccapurple; opacity: 0.75; } jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
html inert attribute jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
inert 102 jessbudd@bsky.social 102 jessbudd@front-end.social 112 15.5 jessbudd44 19 @jessbudd @jessbudd4
WCAG success criteria: 2.4.3 - Focus order (AA) jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
TESTING
Automated + Manual jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Automated jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4
“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4
“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4
“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4
“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4
“I need to learn about accessibility and need to write code that conforms with the WCAG 2.1 level A and AA success criteria de ned at https:// www.w3.org/TR/WCAG21/. I want you to be my accessibility coach, a subject-matter expert that makes me think and account for all accessibility requirements and usability enhancements. When you answer questions about accessibility please use reputable sources such as w3.org, webaim.org, developer.mozilla.org, and https:// www.ibm.com/able/. When possible, please provide links and references for additional learning. When you suggest code please use semantic HTML, ensure it is operable using the keyboard, follow WCAG 2.1 su cient techniques, and follow the ARIA Authoring Practices Guide and related design patterns. Do you understand these instructions?” jessbudd@front-end.social jessbudd44 @jessbudd fi ffi jessbudd@bsky.social @jessbudd4
Are you still using the instructions I provided? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
eslint-plugin-jsx-a11y jessbudd@bsky.social jessbudd@front-end.social eslint-plugin-vuejs-accessibility jessbudd44 @jessbudd @jessbudd4
•Images have alt text •Links have accessible content •Mouse events have key events •Labels have “for” attributes •…and more jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
react-axe jessbudd@bsky.social jessbudd@front-end.social Vue-axe jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Click to edit jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Automated testing is just the first step jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Manual jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
What to look for Can I see where the focus is? Does the tab order make sense? Can I get to all the components? Can all interactive components be activated? jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Screen readers jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Source: 2021 WebAim screen reader survey #9 VoiceOver JAWS 6.5% 53.7% NVDA 30.7% jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Click to edit
VoiceOver TalkBack jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
TalkBack 29% VoiceOver 71% Source: 2021 WebAim screen reader survey #9
What to look for Are all buttons announced correctly? Does link text make sense out of context? Are form labels announced? Announcement of component state jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Summary Using the right HTML Link form labels with inputs Update page titles on routing Manage keyboard focus and make it visible Test your apps jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
Final thought… jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
The web does not just connect machines, it connects people. - Tim Berners-Lee jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4
resources THANK YOU bit.ly/ndcSydney24 jessbudd@bsky.social jessbudd@front-end.social jessbudd44 @jessbudd @jessbudd4