Slide 1
markup
It’s the
that matters
Hidde de Vries, October 27 2020, NextJS Conference
Slide 2
markup
It’s the
that matters
if we want our apps to work for everybody
Slide 3
@hdv
https://www.youtube.com/watch?v=Ug6XAw6hzaw
Slide 4
Accessible for People with permanent disabilities
@hdv
People with temporary disabilities
People in certain situations
Slide 5
Responsibility of Content designers Web developers UI designers CMS integrators User researchers @hdv
Slide 6
Responsibility of Content designers
Web developers UI designers CMS integrators @hdv
User researchers
Slide 7
Code
Assistive Technologies (AT)
text-to-speech screen magnifiers alternate pointing devices
@hdv
Slide 8
Slide 9
Slide 10
Slide 11
Slide 12
Slide 13
Slide 14
Role What kind of thing is it? Name/Description How should we refer to it? State/properties What else should we know?
Slide 15
@hdv
Example of an Accessibility Tree・ https://github.com/WICG/aom/blob/gh-pages/images/a11y-node.png
Slide 16
Accessible code points machines at what stuff is
@hdv
Slide 17
Accessible code points machines at what stuff is called
@hdv
Slide 18
Accessible code points machines in what state stuff is
@hdv
Slide 19
Accessibility tree
Platform APIs
AT
Your markup
DOM tree
Microsoft Active Accessibility Microsoft User Interface Automation MSAA
Mac OS X Accessibility Protocol
text-to-speech Linux/Unix Accessibility Toolkit IAccessible2
screen magnifiers alternate pointing devices
Slide 20
Slide 21
It’s the markup that matters
Slide 22
Slide 23
<html lang=”nl”> <head> <title>It’s the markup that matters Presentations - My site</title> </head> <body> … </body> </html>
Slide 24
“
[The <title>] is still the first guarantee or first confirmation that you’ve ended up on the page that you intended to reach. — Léonie Watson, accessibility expert and screenreader user
Smashing TV with Léonie Watson・ https://www.youtube.com/watch?v=iUCYPM6up9M.
Slide 25
What’s on this page? Headings
Slide 26
“Navigate by heading” is a very common way for AT users to figure out what’s on a page
Heading structures are tables of contents ・ https://hiddedevries.nl/en/blog/2018-09-01-heading-structures-are-tables-of-contents
Slide 27
Slide 28
What’s on this page? Landmarks
Slide 29
Landmarks let you specify which sections a page has, so that people can navigate to them
Slide 30
HTML5
ARIA roles
<header> <footer> <nav> <aside> <main>
role=”banner” role=”contentinfo” role=”navigation” role=”complementary” role=”main”
Slide 31
“
Built-in beats bolt-on. — Bruce Lawson
Bruce Lawson: AOM-NOM-NOM・ https://noti.st/brucelawson/wLB2lE/aom-nom-nom#sgf2LTe
Slide 32
HTML5 <header> <footer> <nav> <aside> <main>
Slide 33
Slide 34
“
“59% of form inputs were not properly labeled.”. — WebAIM
The WebAIM Million ・ https://webaim.org/projects/million/
Slide 35
Label input fields, radio buttons, checkboxes, selects, textareas, etc… so that they have a name
Slide 36
First Name
<div class=”form-item”> First Name <input type=”text” /> </div>
Role: ‘textbox’ / ‘entry’ Name: null / ”
Slide 37
Accessible Name and Description Computation 1.1 ・ https://www.w3.org/TR/accname-1.1/
Slide 38
First Name
<div class=”form-item”> <label for=”fn”>First Name</label> <input id=”fn” type=”text” /> </div>
Role: ‘textbox’ / ‘entry’ Name: ‘First Name’
Slide 39
Slide 40
Tables make tabular data easier to navigate
Slide 41
<table> <caption>Net results 2018</caption> <thead> <tr> <th scope=”col”>Assets</th>
Use table semantics
<th scope=”col”>Capital</th> … </tr> </thead> <tbody> … </tbody> </table>
Slide 42
Slide 43
<table> <caption>Net results 2018</caption> <thead> <tr> <th scope=”col”>Assets</th>
Use table semantics
<th scope=”col”>Capital</th> … </tr> </thead> <tbody> … </tbody> </table>
Slide 44
Slide 45
The lang attribute lets you specify which language content is in
Slide 46
Specify languages with lang <div> <p lang=”de”>Wilkommen</p> <p lang=”fr”>Bienvenue</p> <p lang=”en”>Welcome</p> </div>
Slide 47
If buttons are just icons
Slide 48
The “Add Reaction” button
Slide 49
<div class=”icon” onclick=”emoji()”> <svg class=”icon”> <use xlink:href=”#emoji”></use> </svg> </div>
Role: ” Name: ”
Slide 50
// use the button element <button type=”button”> <svg class=”icon”> <use xlink:href=”#emoji”></use> </svg> </button>
Role: ‘button’ Name: ”
Slide 51
<button type=”button”> <svg class=”icon”> <use xlink:href=”#emoji”></use> </svg> // add accessible name <span class=”visually-hidden”> Add reaction </span> </button>
Role: ‘button’ Name: ‘Add reaction’
Slide 52
<button type=”button”> // hide icon from a11y tree <svg class=”icon” role=”presentation”
“Accessibility node not exposed”
aria-hidden=”true” focusable=”false”> <use xlink:href=”#emoji”></use> </svg> <span class=”visually-hidden”>
Slide 53
“
It would appear that either aria-hidden=”true” or role=”presentation” should be able to help out here. — John Foliot
HTML5 Accessibility: aria-hidden and role=”presentation” ・ http://john.foliot.ca/aria-hidden/
Slide 54
<button type=”button”> <svg class=”icon” role=”presentation” aria-hidden=”true” focusable=”false”>
Avoids weird focus bugs in IE11
<use xlink:href=”#emoji”></use> </svg> <span class=”visually-hidden”> Add reaction
Slide 55
No meaningful mark-up for your component? ARIA can polyfill!
Slide 56
ARIA can provide names, roles, property and states through attributes.
Accessible Rich Internet Applications (WAI-ARIA) 1.1 ・ https://www.w3.org/TR/wai-aria/
Slide 57
There usually is existing HTML for your problem, combining existing elements FTW!
Web Components as compositions of native elements ・ https://hiddedevries.nl/en/blog/2017-10-19-web-components-as-compositions-of-native-elements
Slide 58
Not all ARIA has good support or provides good usability for AT users.
Slide 59
Slide 60
Tooltip <button
Enter your IBAN number ?
type=”button” aria-controls=”tooltip”
An IBAN-number is a 34 characters string, please double check with your bank if you’re not sure what yours is.
What’s IBAN? </button>
<div id=”tooltip”> An IBAN-number is a 34 ch… </div>
Slide 61
Tooltip <button
Enter your IBAN number ?
type=”button” aria-controls=”tooltip”
An IBAN-number is a 34 characters string, please double check with your bank if you’re not sure what yours is.
aria-expanded=”true” > What’s IBAN? </button>
<div id=”tooltip”> An IBAN-number is a 34 ch…
Slide 62
Tooltip <button
Enter your IBAN number ?
type=”button” aria-controls=”tooltip” aria-expanded=”false” > What’s IBAN? </button>
<div id=”tooltip” hidden> An IBAN-number is a 34 ch…
Slide 63
Slide 64
Your changes were saved successfully!
Slide 65
<div role=”alert”> </div>
// We’ve just used fetch() to POST form // data on the submit event of a form. // Let’s say we’re handling like:
const el = document.querySelector(“div”);
el.textContent(“Your changes were saved successfully”);
Your changes were saved successfully!
Slide 66
Meaning without mark-up: the Accessibility Object Model
Slide 67
“
“a JavaScript API to allow developers to modify (and eventually explore) the accessibility tree for an HTML page” — The AOM explainer document
The Accessibility Object Model (AOM) ・ https://github.com/WICG/aom
Slide 68
“
“[AOM] fills the gaps in ARIA (…) is an API to provide your own accessibility (…) lets authors test them from JavaScript” — Domenic Mizzoni, Google
What’s new in web accessibility (Google I/O ‘18) ・ https://www.youtube.com/watch?v=wkvslBGkhZY
Slide 69
const el = document.querySelector(“el”);
el.role = “button”; el.ariaDisabled = false;
Setting semantics without mark-up
Slide 70
<my-custom-element role=”button” aria-disabled=”false” … />
Avoids “sprouting”
Slide 71
Relationships without IDREFs
Slide 72
aria-activedescendant aria-colcount aria-colindex aria-colspan aria-controls aria-describedby aria-details aria-errormessage
aria-flowto aria-labelledby aria-owns aria-posinset aria-rowcount aria-rowindex aria-rowspan aria-setsize
Slide 73
Events from Assistive Technologies
Slide 74
// Implementing a canvas-based // spreadsheet’s semantics canvas.attachAccessibleRoot();
let table = canvas.accessibleRoot .appendChild(new AccessibleNode());
table.role = “table”; table.colCount = 10; table.rowcount = 100;
Non-DOM nodes in the Accessibility Tree
let headerRow = table.appendChild( appendChild(new AccessibleNode()) ); headerRow.role = “row”; headerRow.rowindex = 0; Example from: AOM explainer
・ https://wicg.github.io/aom/explainer.html#the-accessibility-object-model
Slide 75
Reading accessibility tree through JavaScript
Slide 76
Slide 77
Quality future components need to be accessible Good mark-up makes a difference, gives us lots of accessibility for free Whatever the mark-up, convey what it is, and what state it is in
Slide 78
Thanks! Questions? TWITTER: @hdv EMAIL:
hidde@hiddedevries.nl
SLIDES:
https://talks.hiddedevries.nl