A presentation at ffconf in in Brighton, UK by Ire Aderinokun
Web Accessibility: it’s not just about HTML Ire Aderinokun @ ffconf 2023 @ireaderinokun / @ire@front-end.social
“By default, HTML is accessible. Web accessibility involves ensuring that content remains accessible.” https://developer.mozilla.org/en-US/docs/Learn/Accessibility
Web accessibility is the inclusive practice of ensuring there are no barriers that prevent access to websites
Physical disabilities
Situational disabilities
Socio-economic restrictions
Accessibility is about inclusion
“By default, HTML is accessible. Web accessibility involves ensuring that content remains accessible.” https://developer.mozilla.org/en-US/docs/Learn/Accessibility
“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
https://ireade.github.io/motherduckingwebsite/
HTML can be inaccessible
Missing text alternatives ☹ <img src=“link/to/really-important-image.png”
Using the wrong elements ☹ <span>Enter your username:</span> <input type=“text”>
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>HTML
JavaScript CSS
Adding content with CSS ☹
<div id=“important”></div> #important after { content: “Really important information that everyone should know” : : }Altering element behaviour with JavaScript ☹
<div onClick=“goToPage(‘/about’)”> About Us </div>90% of accessibility is about using HTML correctly. The other 10% is about not using CSS/JS incorrectly.
CSS, JavaScript, & Accessibility
Part One CSS & Accessibility
CSS is used to describe the presentation of an HTML document
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>
CSSOM body { font-size: 18px; } header { color: plum; } h1 { font-size: 28px; } main { color: firebrick; } h2 { font-size: 20px; } footer { display: none; }
DOM + CSSOM - Non-visible elements = Render tree
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>
#1 Don’t use CSS to convey meaning or content
<input class=“error” > <input class=“success” > .error { border-color: red; } .success { border-color: green; }
h1 after { content: “My Page Title” : : }
https://tink.uk/accessibility-support-for-css-generated-content/
“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/
#2 Don’t use CSS to change the semantics of HTML
display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅
display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅
display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅
https://frend.co/components/tooltip/
display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅
display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅
Don’t use visibility: hidden;
display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅
display: none; visibility: hidden; opacity: 0; position: absolute; top: -9999px; left: -9999px; Visually hidden? ✅ ✅ ✅ ✅ Box model generated? ❌ ✅ ✅ ✅ Affects layout? ❌ ✅ ✅ ❌ Read by assistive technologies? ❌ ❌ ✅ ✅
Source Order Visual Order
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>“With this power comes great responsibility” — Rachel Andrew https://rachelandrew.co.uk/archives/2015/07/28/modern-css-layout-power-and-responsibility/
#3 Don’t write CSS that undoes the default accessible styles
Browser CSS
✅ Text & element sizes ✅ Colours & contrast ✅ Hover, focus, & active states
My CSS Browser CSS
button { font-size: 6px; }
button { color: lightgray; }
https://uxplanet.org/active-hover-and-focus-states-for-designers-d789531fe767
https://bitsofco.de/when-do-the-hover-focus-and-active-pseudo-classes-apply/
: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; }
❌ ✅ :focus { :focus { outline: none; outline: none; other focus styles } / * * / }
button:focus:not(:focus-visible) { outline: none; } button:focus-visible { background-color: darksalmon; }
Write custom CSS cautiously
#4 Do use CSS to improve on the default accessible styles
Guideline 1.4.8 — Visual presentation
The default browser styling doesn’t meet these requirements
p { line-height: 1.5; padding: 2.25rem; max-width: 80ch; }
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).
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.
#5 Do adapt CSS to device capabilities
CSS
.element { color: #000; color: var(—text-color); }
.element { color: #000; color: var(—text-color); }
.element { color: #000; color: var(—text-color); }
@supports ( declaration ) { Feature-based CSS here / * * / }
Legacy code Modern code @supports (display: grid) { main { main { display: grid; display: table; } } more layout code / * * / }
Legacy code Modern code @supports (display: grid) { main { main { display: grid; display: table; } } more layout code / * * / }
#6 Do adapt CSS to user preferences
https://dbaron.org/css/user/
https://codereview.chromium.org/64843004
“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
@media ( prefers-* ) { Preference-based CSS here / * * / }
Adapt to motion preferences .element { animation: bouncing 1.5s linear infinite alternate; } @media ( prefers-reduced-motion: reduce ) { .element { animation: fade 0.5s ease-in both; } } https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/
Adapt to motion preferences prefers-reduced-motion Adapt to data preferences prefers-reduced-data Adapt to colour preferences prefers-color-scheme Adapt to contrast preferences prefers-contrast Adapt to trasparency preferences prefers-reduced-transparency
Giving users control
CSS & Accessibility 1. Don’t use CSS to convey meaning or content
Part Two JavaScript & Accessibility
JavaScript is used to make web pages more interactive
JavaScript is used to make web pages more interactive
#1 Don’t use JavaScript for functionality HTML provides
✅ Triggered by mouse, enter key, and space bar ✅ Focusable via the keyboard and other input devices ✅ Accessible name and state provided to assistive tech
<button> Do something </button>
Extra work 😓 <div tabindex=“0” role=“button” onKeyPress=“handleBtnKeyPress(e)” onClick=“doSomething(e)”> Do something </div>
Extra work 😓 <div tabindex=“0” role=“button” onKeyPress=“handleBtnKeyPress(e)” onClick=“doSomething(e)”> Do something </div>
Extra work 😓 <div tabindex=“0” role=“button” onKeyPress=“handleBtnKeyPress(e)” onClick=“doSomething(e)”> Do something </div>
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> = = = = = = }Even more extra work 🥵 <div tabindex=“0” role=“button” onKeyPress=“handleBtnKeyPress(e)” onClick=“doSomething(e)” aria-pressed=”false”> Toggle </div>
✅ ❌ <button onClick=“goToPage(‘/about’)”> <a href=“/about”>About Us</a> About Us </button>
<button onClick=“goToPage(‘/about’)”> About Us </button> function goToPage(url) { // Do some other things window.location.href = url; }
Keep JavaScript enhancements unobtrusive
<a href=“/about” onClick=“goToPage(e, ’/about’)”> About Us </a> function goToPage(e, url) { e.preventDefault(); // Do some other things window.location.href = url; }
<a href=“/about” onClick=“goToPage(event, ’/about’)”> About Us </a> function goToPage(event, url) { event.preventDefault(); // Do some other things window.location.href = url; }
<a href=“/about” onClick=“goToPage(e, ’/about’)”> About Us </a> function goToPage(e, url) { e.preventDefault(); // Do some other things window.location.href = url; }
event.preventDefault() is the 🔑
#2 Where possible, don’t require JavaScript for critical features
Without JS With JS
Without JS With JS
“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/
Different groups have different access needs
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%.
People with socio-economic restrictions are more likely to avoid JS Over 50% of the Sudanese mobile browsing is with Opera Mini
Average File Sizes 430 KB 27 KB HTML 66 KB CSS https://almanac.httparchive.org/en/2021/page-weight JS
JavaScript-disabled experience JavaScript-enabled experience
JavaScript-enabled experience JavaScript-disabled experience
JavaScript-disabled experience JavaScript-enabled experience
“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/
“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/
#3 Do use JavaScript to improve on the default accessible behaviour
Guideline 3.3 — Help users avoid and correct mistakes ✅
Guideline 3.3.3 — When an error is detected and suggestions for correction are known, provide these to the user
Some HTML elements aren’t accessible enough, yet ☹
Problems with <video> ❌ Controls not focusable via keyboard ❌ Can’t pause/play video using space key ❌ No arrow key support for scrubber & more
“Modern browsers provide a default media player. Most have limited functionality to support accessibility.” https://www.w3.org/WAI/media/av/player/
https://www.digitala11y.com/accessible-jquery-html5-media-players/
Sometimes, we need JavaScript
#4 Do use JavaScript to create components that don’t exist
https://www.w3.org/TR/2021/NOTE-wai-aria-practices-1.2-20211129/examples/carousel/carousel-1-prev-next.html
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
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
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
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
Write custom components cautiously
https://www.w3.org/TR/2021/NOTE-wai-aria-practices-1.2-20211129/examples/
https://frend.co/
https://inclusive-components.design/
JavaScript & Accessibility 1. Don’t use JavaScript for functionality HTML provides 2. Where possible, don’t require JavaScript for critical features
“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
“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
Thank you! Ire Aderinokun 🇳🇬 🇬🇧 Independent User Interface Engineer Google Web Expert Co-Founder Helicarrier ireaderinokun.com bitsofco.de @ireaderinokun / @ire@front-end.social / @ire.bsky.social
HTML is, by default, accessible. More often than not, what makes a web page less accessible is the CSS and JavaScript we add. In this talk, we’ll explore how these tools can be used in a more positive way to make web pages even more accessible.
Here’s what was said about this presentation on social media.
Thank you for your talk today - I was nodding along all the way!! Brilliantly structured, clear and concise. I will be sure to share with my colleagues as it was such a great explanation of many points 👍🏼👍🏼🙂
— Ian Ovenden (@ianovenden) November 10, 2023