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

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

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

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

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

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

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

@hdv

@hdv

@hdv

@hdv

@hdv

@hdv

Role What kind of thing is it? Name/Description How should we refer to it? State/properties What else should we know?

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

Accessible code points machines at what stuff is @hdv

Accessible code points machines at what stuff is called @hdv

Accessible code points machines in what state stuff is @hdv

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

It’s the markup that matters

What’s this page?

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

“ [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.

What’s on this page? Headings

“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

What’s on this page? Landmarks

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

HTML5 ARIA roles

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

“ Built-in beats bolt-on. — Bruce Lawson Bruce Lawson: AOM-NOM-NOM・ https://noti.st/brucelawson/wLB2lE/aom-nom-nom#sgf2LTe

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

Form controls

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

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

First Name

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

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

First Name

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

Table semantics

Tables make tabular data easier to navigate

<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>

<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>

Language

The lang attribute lets you specify which language content is in

Specify languages with lang <div> <p lang=”de”>Wilkommen</p> <p lang=”fr”>Bienvenue</p> <p lang=”en”>Welcome</p> </div>

If buttons are just icons

The “Add Reaction” button

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

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

<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’

<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”>

“ 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/

<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

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

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/

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

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

Expandables

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>

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…

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…

Announcements

Your changes were saved successfully!

<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!

Meaning without mark-up: the Accessibility Object Model

“ “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

“ “[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

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

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

Relationships without IDREFs

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

Events from Assistive Technologies

// 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

Reading accessibility tree through JavaScript

TLDR

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

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