Accessibility notes
My notes for making the web more inclusive. Don't follow this guide blindly. Read the references to learn more about certain rules.
Check out my general best practices for building better applications.
This page is a continuous work in progress.
Where to start?
Accessibility fundamentals are covered in the Web Fundamentals Guide (Google) and the Web Accessibility Course (Udacity/Google). Both resources are free.
To evaluate the accessibility of a web page, try out the following tools:
- Chrome/Firefox browser extension: WAVE
- Command line: evaluatory
Resources
- WCAG Quick Reference
- WAI-ARIA Authoring Practices 1.2
- A11y Reviews (GitHub)
- Accessibility interview questions
- IBM Accessibility Checklist 7.1
- Accessibility motivation
Collections
General
Motivation
- Web accessibility means that the site's functionality can be operated by literally anyone, including people with impairments or disabilities.
- Disability accommodations often benefit everyone, not just disabled people. Think about wheelchair ramps: parents pushing a stroller, someone walking a bicycle, or someone towing a heavy load on wheels.
Best practices
- Provide a correct lang attribute.
- Ensure that interactive controls have at least a 44×44 pixels target click size.
Libraries
- Accessible, responsive canvas.
- a11y-dialog - Accessible JS modal dialog.
- Comica11y - accessible comics.
Tools / Audit
- PDF Accessibility Checker (PAC)
- Accessibility tools audit — An example page to test the effectiveness of accessibility tools.
- There are multiple issues with AccessiBe and other overlays.
- Building the most inaccessible site possible with a perfect Lighthouse score.
Stories
- The WebAIM Million - An annual accessibility analysis of the top 1,000,000 home pages.
- Losing sight.
- I'm a software engineer going blind, how should I prepare?.
- A blog where the author describes their way to become certified in WAS and CPACC.
Language
- It is okay to use the word "disabled".
Focus indicator
- Consider different implementation techniques.
- The focus indicator must have a contrast ratio of 3:1 against its adjacent elements, or be at least 2px wide. (WCAG 2.2)
- The focus indicator must have a 3:1 (AA) / 4.5:1 (AAA) contrast ratio between its focused and unfocused states. (WCAG 2.2)
- It is not required that hover as a state is differentiated from the default (and presumably all other) states.
- Adjusting the flex order does not change the focus order.
- Provide a fallback for Windows High Contrast mode when using a
box-shadow
focus indicator. - A keyboard-only focus ring has pros and cons, but it is technically possible using
:focus-visible
. Progressive enhancement handles older browsers. - Enable proper tab behavior on Mac
- ☑ System Preferences → Keyboard → Shortcuts → Accessibility → Full Keyboard Access → All controls
- ☑ Safari Preferences → Advanced → Press Tab to highlight each item on a webpage
Colors / Contrast Ratio
Labels
- Alt-Texts — The Ultimate Guide.
- Add punctuation to your alt text.
- There are limitations of
aria-label
,aria-labelledby
andaria-describedby
. It's complicated. - Google Translate does not translate
aria-label
labels. Sometimes it does. - HTML for vs wrapping label.
Fonts
- There's no evidence that typefaces designed to help dyslexics have any effect.
- Accessible font types.
- Atkinson Hyperlegible Font.
WCAG / WAI-ARIA
- Eleventy starter for WCAG reports
- WCAG-compliant website showcase
- Rules for using ARIA.
- An in-depth guide to ARIA roles.
- Boolean ARIA attributes behave differently than HTML Boolean attributes:
required="true"
,required="false"
andrequired="foo"
have the same effect and mark the referenced element as "required".aria-required="true"
andaria-required="false"
consider the used value (either "true" or "false").
- ARIA IDL interface provides a simplified way to access ARIA attributes in JavaScript. However, as of July 2021, the browser support is not good enough.
- A
password
role is under discussion. - The
role="none"
is not supported in IE11. - Do not put
aria-hidden
on focusable elements. - Keyboard shortcuts need modifier keys.
aria-description
is in W3C Editor's Draft for ARIA 1.3, but some browsers already support it.
Miscellaneous
- Using tabs over spaces in code is more accessible to braille device users.
- The anatomy of visually-hidden.
Screen reader
- NVDA Keyboard Shortcuts
- User survey 2019 (browser/screen reader usage)
- Do not use screen reader detection.
- Do not override screen reader pronunciation.
- Screen reader icon (public domain):
Support
Announcement
- A screen reader may announce things differently than displayed in the text viewer. Pay attention to times, dates, currency, punctuation, special characters, emoji, math symbols, common (and uncommon) abbreviations & acronyms.
- Screen reader's punctuation announcement depends on its order, e.g. NVDA announces question marks only at the end of a sentence by default.
- Minus the minus - A PSA about screen readers and negative numbers.
- Use
−
(−
) instead of a dash for negative numbers. - NVDA has fixed a related issue.
- Talkback doesn't recognize the
-
character correctly.
- Use
- Acronyms can usually be left as-is.
- NVDA announces values differently between divs and spans.
- NVDA does not announce emphasis elements (like
em
orstrong
). - Superscript and subscript are announced inconsistently.
- Improve the announcement of phone numbers:
<a href="tel:70355512" aria-label="7 0 3. 5 5 5. 1 2.">(703) 555-12</a>
::before
and::after
content is screen reader accessible (except IE11).- CSS generated content is not fully accessible.
- A live region will announce changes coming from a CSS counter.
- Defining an alternative text for CSS
content
.
- How the
display
properties affect<table>
,<ul>
,<ol>
,<dl>
,<h#>
,<button>
. - German gender characters are not excluding screen reader users.
- For a live region to announce its content changes:
- The live region should be available in the DOM before changing the content.
- The live region must not be hidden (e.g. via
display: none
).
NVDA
- Settings:
- ☑ Tools → Speech viewer
- ☑ Show Speech Viewer on Startup
- ☑ Preferences → Keyboard → Select NVDA Modifier Keys → caps lock
- ☑ Tools → Speech viewer
- Addons:
- Notes:
- NVDA does not focus inline links in browse mode, unless the link appears at the start of a line.
VoiceOver
- Shortcuts:
- Start:
Cmd
+F5
- Start:
- Settings:
- ☐ Verbosity → Hints → Speak instructions for using the item in the VoiceOver cursor
- ☑ Sound → Mute sound effects
Dragon
- Notes:
- Dragon does not support wrapping labels for inputs.
Content
- It is fine to use hashtags within social media posts. Use
#CamelCase
for better readability.
Elements and Widgets
- HTML: The Inaccessible Parts.
- Avoid the strikethrough element, as the semantics are not announced by screen readers.
- Use buttons for actions and links for links.
- If it makes sense to "open in new tab", then it should be a link. Otherwise, it's a button.
Date Picker
Something I see (...) is the frustration with date fields that are anything other than a plain text field for well-known dates (like birthdays).
Definition Lists
<dl>
<dt>Coffee</dt>
<dd>Black hot drink</dd>
<dt>Milk</dt>
<dd>White cold drink</dd>
</dl>
- Wrappings divs are allowed.
- NVDA does not expose definition lists correctly, but:
It's worth noting that a definition list is the correct way to mark up a list of paired items. Changing markup patterns to satisfy the vagaries of specific assistive technologies tends to be a slippery slope. (source)
Dialog / Modal
- There is no fixed rule where the focus should be moved to after opening a modal. A headline or the dialog itself are two good possibilities. There is an ongoing discussion about the default behavior for the HTML
dialog
element.
Fieldset
- Read about using legend and fieldset.
- A
legend
has to be a direct child of afieldset
. A screen reader might not announce the label if the markup is malformed (e.g. NVDA). Solutions:- Use
role="group"
+aria-labelledby
instead. - Use a duplicate label
- Use
- There was a Chrome bug, making it impossible to adjust the
fieldset
display
value.
Footer
There are some rules regarding the <footer>
element:
- The HTML footer element defines a
contentinfo
landmark when its context is the body element. - The HTML footer element is not considered a contentinfo landmark when it is a descendant of any of following elements:
article
,aside
,main
,nav
,section
A contentinfo landmark role is used to identify information repeated at the end of every page of a website, hence a page should not have more than one contentinfo landmark.
Headline
- An H1 doesn't have to come first (example).
- These are no WCAG violations, but should still be avoided:
- Missing or more than one
<h1>
. - Skipping heading levels.
- Multiple headings with the same text.
- Missing or more than one
Images
- Decorational images:
We tried to outsmart screen readers by letting them skip descriptive images. This turned out to be really unhelpful. Users that are not fully blind will still see an image and when the screen reader skips these images, users will assume they missed out on information. Solution: let the screen reader tell the users it’s a descriptive image. Or even better, write a descriptive alt-text for images. source
- Background images are mostly ignored in Windows High Contrast mode.
Inputs
- Avoid the native field validation.
- Prefer
type="search"
for search inputs, even though it currently offers little benefit. - Screen readers don't announce the maxlength attribute.
Links
- The perfect link
- Links don't require an underline effect when using a contrast ratio of 3:1 and a visual cue on focus. It is still recommended to use a visual cue other than color.
- Icon-only links fail WCAG 2.4.4.
- Accessible anchor links
- Mark links that open in a new window:
<div hidden>
<span id="new-window-0">Opens in a new window</span>
<span id="new-window-1">Opens an external site</span>
<span id="new-window-2">Opens an external site in a new window</span>
</div>
<a
href="https://example.com"
target="_blank"
rel="noopener"
aria-describedby="new-window-0"
>
My site
</a>
- Download links:
- Use
<a>
, not a<button>
. - Provide media type and file size visually readable.
- Use
- The trouble with mailto email links and what to do instead.
Buttons
- There is a difference when pressing Enter or Space with buttons:
- A native
<button>
fires on key down when that key isEnter
. If you hold down theEnter
key, it continues to fire for as long you holdEnter
(or something crashes). - A native
<button>
fires on key up when that key isSpace
. If you do not release theSpace
, and also pressTab
to move away from the control, the control will not fire.
- A native
- Whether the pointer cursor applies to buttons is controversial.
SVGs
<svg role="img">
<title>Lightbulb moment!</title>
<path d="..." />
</svg>
Lists
- Safari [removes list semantics] for
list-style: none
lists.
Tables
- Include a table caption:
<table>
<caption>Populations of cities</caption>
<thead>...</thead>
<tbody>...</tbody>
</table>