It’s the markup that matters

A presentation at Next.js Conf in October 2020 in by Hidde de Vries

Slide 1

Slide 1

markup It’s the that matters Hidde de Vries, October 27 2020, NextJS Conference

Slide 2

Slide 2

markup It’s the that matters if we want our apps to work for everybody

Slide 3

Slide 3

@hdv https://www.youtube.com/watch?v=Ug6XAw6hzaw

Slide 4

Slide 4

Accessible for People with permanent disabilities @hdv People with temporary disabilities People in certain situations

Slide 5

Slide 5

Responsibility of Content designers Web developers UI designers CMS integrators User researchers @hdv

Slide 6

Slide 6

Responsibility of Content designers Web developers UI designers CMS integrators @hdv User researchers

Slide 7

Slide 7

Code Assistive Technologies (AT) text-to-speech screen magnifiers alternate pointing devices @hdv

Slide 8

Slide 8

@hdv

Slide 9

Slide 9

@hdv

Slide 10

Slide 10

@hdv

Slide 11

Slide 11

@hdv

Slide 12

Slide 12

@hdv

Slide 13

Slide 13

@hdv

Slide 14

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

Slide 15

@hdv Example of an Accessibility Tree・ https://github.com/WICG/aom/blob/gh-pages/images/a11y-node.png

Slide 16

Slide 16

Accessible code points machines at what stuff is @hdv

Slide 17

Slide 17

Accessible code points machines at what stuff is called @hdv

Slide 18

Slide 18

Accessible code points machines in what state stuff is @hdv

Slide 19

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 20

Slide 21

Slide 21

It’s the markup that matters

Slide 22

Slide 22

What’s this page?

Slide 23

Slide 23

<html lang=”nl”> <head> <title>It’s the markup that matters Presentations - My site</title> </head> <body> … </body> </html>

Slide 24

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

Slide 25

What’s on this page? Headings

Slide 26

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 27

Slide 28

Slide 28

What’s on this page? Landmarks

Slide 29

Slide 29

Landmarks let you specify which sections a page has, so that people can navigate to them

Slide 30

Slide 30

HTML5 ARIA roles

<header> <footer> <nav> <aside> <main> role=”banner” role=”contentinfo” role=”navigation” role=”complementary” role=”main”

Slide 31

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

Slide 32

HTML5 <header> <footer> <nav> <aside> <main>

Slide 33

Slide 33

Form controls

Slide 34

Slide 34

“ “59% of form inputs were not properly labeled.”. — WebAIM The WebAIM Million ・ https://webaim.org/projects/million/

Slide 35

Slide 35

Label input fields, radio buttons, checkboxes, selects, textareas, etc… so that they have a name

Slide 36

Slide 36

First Name

<div class=”form-item”> First Name <input type=”text” /> </div> Role: ‘textbox’ / ‘entry’ Name: null / ”

Slide 37

Slide 37

Accessible Name and Description Computation 1.1 ・ https://www.w3.org/TR/accname-1.1/

Slide 38

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 39

Table semantics

Slide 40

Slide 40

Tables make tabular data easier to navigate

Slide 41

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 42

Slide 43

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 44

Language

Slide 45

Slide 45

The lang attribute lets you specify which language content is in

Slide 46

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

Slide 47

If buttons are just icons

Slide 48

Slide 48

The “Add Reaction” button

Slide 49

Slide 49

<div class=”icon” onclick=”emoji()”> <svg class=”icon”> <use xlink:href=”#emoji”></use> </svg> </div> Role: ” Name: ”

Slide 50

Slide 50

// use the button element <button type=”button”> <svg class=”icon”> <use xlink:href=”#emoji”></use> </svg> </button> Role: ‘button’ Name: ”

Slide 51

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

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

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

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

Slide 55

No meaningful mark-up for your component? ARIA can polyfill!

Slide 56

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

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

Slide 58

Not all ARIA has good support or provides good usability for AT users.

Slide 59

Slide 59

Expandables

Slide 60

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

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

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 63

Announcements

Slide 64

Slide 64

Your changes were saved successfully!

Slide 65

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

Slide 66

Meaning without mark-up: the Accessibility Object Model

Slide 67

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

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

Slide 69

const el = document.querySelector(“el”); el.role = “button”; el.ariaDisabled = false; Setting semantics without mark-up

Slide 70

Slide 70

<my-custom-element role=”button” aria-disabled=”false” … /> Avoids “sprouting”

Slide 71

Slide 71

Relationships without IDREFs

Slide 72

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

Slide 73

Events from Assistive Technologies

Slide 74

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

Slide 75

Reading accessibility tree through JavaScript

Slide 76

Slide 76

TLDR

Slide 77

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

Slide 78

Thanks! Questions? TWITTER: @hdv EMAIL: hidde@hiddedevries.nl SLIDES: https://talks.hiddedevries.nl