- First impressions
- The Tab key
- Automated testing tools
- Screen reader testing
- Next steps
Thursday, November 12th, 2020
Wednesday, October 21st, 2020
Accessibility on the web is easy. Accessibility on the web is also hard.
I think it’s one of those 80/20 situations. The most common accessibility problems turn out to be very low-hanging fruit. Take, for example, Holly Tuke’s list of the 5 most annoying website features she faces as a blind person every single day:
- Unlabelled links and buttons
- No image descriptions
- Poor use of headings
- Inaccessible web forms
- Auto-playing audio and video
None of those problems are hard to fix. That’s what I mean when I say that accessibility on the web is easy. As long as you’re providing a logical page structure with sensible headings, associating form fields with labels, and providing alt text for images, you’re at least 80% of the way there (you’re also doing way better than the majority of websites, sadly).
Ah, but that last 20% or so—that’s where things get tricky. Instead of easy-to-follow rules (“Always provide alt text”, “Always label form fields”, “Use sensible heading levels”), you enter an area of uncertainty and doubt where there are no clear answers. Different combinations of screen readers, browsers, and operating systems might yield very different results.
This is the domain of interaction design. Here be dragons. ARIA can help you …but if you overuse its power, it may cause more harm than good.
When I start to feel overwhelmed by this, I find it’s helpful to take a step back. Instead of trying to imagine all the possible permutations of screen readers and browsers, I start with a more straightforward use case: keyboard users. Keyboard users are (usually) a subset of screen reader users.
The pattern that comes up the most is to do with toggling content. I suppose you could categorise this as progressive disclosure, but I’m talking about quite a wide range of patterns:
- menus (including mega menu monstrosities),
- modal dialogs,
In each case, there’s some kind of “trigger” that toggles the appearance of a “target”—some chunk of content.
The first question I ask myself is whether the trigger should be a button or a link (at the very least you can narrow it down to that shortlist—you can discount
spans, and most other elements immediately; use a trigger that’s focusable and interactive by default).
As is so often the case, the answer is “it depends”, but generally you can’t go wrong with a button. It’s an element designed for general-purpose interactivity. It carries the expectation that when it’s activated, something somewhere happens. That’s certainly true in all the examples I’ve listed above.
That said, I think that links can also make sense in certain situations. It’s related to the second question I ask myself: should the target automatically receive focus?
Again, the answer is “it depends”, but here’s the litmus test I give myself: how far away from each other are the trigger and the target?
If the target content is right after the trigger in the DOM, then a button is almost certainly the right element to use for the trigger. And you probably don’t need to automatically focus the target when the trigger is activated: the content already flows nicely.
<button>Trigger Text</button> <div id="target"> <p>Target content.</p> </div>
But if the target is far away from the trigger in the DOM, I often find myself using a good old-fashioned hyperlink with a fragment identifier.
<a href="#target">Trigger Text</a> … <div id="target"> <p>Target content.</p> </div>
The expectation with links (as opposed to buttons) is that you will be taken somewhere. Let’s face it, modal dialogs are like fake web pages so following through on that expectation makes sense in this context.
So I can answer my first two questions:
- “Should the trigger be a link or button?” and
- “Should the target be automatically focused?”
…by answering a different question:
- “How far away from each other are the trigger and the target?”
It’s not a hard and fast rule, but it helps me out when I’m unsure.
tabindex action, and maybe a
Now I can start to think about making sure screen reader users aren’t getting left out. At the very least, I can toggle an
aria-expanded attribute on the trigger that corresponds to whether the target is being shown or not. I can also toggle an
aria-hidden attribute on the target.
When the target isn’t being shown:
- the trigger has
- the target has
When the target is shown:
- the trigger has
- the target has
There’s also an
aria-controls attribute that allows me to explicitly associate the trigger and the target:
<button aria-controls="target">Trigger Text</button> <div id="target"> <p>Target content.</p> </div>
But don’t assume that’s going to help you. As Heydon put it,
Here’s some example code I wrote a while back. And here are some old Codepens I made that use this pattern: one with a button and one with a link. See the difference? In the example with a link, the target automatically receives focus. But in this situation, I’d choose the example with a button because the trigger and target are close to each other in the DOM.
At this point, I’ve probably reached the limits of what can be abstracted into a single trigger/target pattern. Depending on the specific component, there might be much more work to do. If it’s a modal dialog, for example, you’ve got to figure out where to put the focus, how to trap the focus, and figure out where the focus should return to when the modal dialog is closed.
I’ve mostly been talking about websites that have some interactive components. If you’re building a single page app, then pretty much every single interaction needs to be made accessible. Good luck with that. (Pro tip: consider not building a single page app—let the browser do what it has been designed to do.)
Anyway, I hope this little stroll through my thought process is useful. If nothing else, it shows how I attempt to cope with an accessibility landscape that looks daunting and ever-changing. Remember though, the fact that you’re even considering this stuff means you care more than most web developers. And you are not alone. There are smart people out there sharing what they learn. The A11y Project is a great hub for finding resources.
And when it comes to interactive patterns like the trigger/target examples I’ve been talking about, there’s one more question I ask myself: what would Heydon do?
Thursday, October 8th, 2020
Considering how much accessibility work happens “under the hood”, it’s interesting that all five of these considerations are visibly testable.
- Think about accessible copy
- Don’t forget about the focus indicator
- Check your colour contrast
- Don’t just use colour to convey meaning
- Design in anticipation of text resizing
Wednesday, June 17th, 2020
Amber documents a very handy bit of DOM scripting when it comes to debugging focus management:
Wednesday, June 10th, 2020
Smart thinking from Sara to improve usability for keyboard users by using
aria-hidden="true" tabindex="-1" to skip duplicate links:
A good rule of thumb for similar cases is that if you have multiple consecutive links to the same page, there is probably a chance to improve keyboard navigation by skipping some of those links to reduce the number of tab stops to one. The less tab stops, the better, as long as it does not worsen or compromise on other aspects of usability.
I’ve cautiously implemented this pattern now over on The Session where snippets of comments had both a title link and a “more” link going to the same destination.
Monday, April 6th, 2020
Chromium browsers—Chrome, Edge, et al.—are getting a much-needed update to some interface elements like the
progess element, the
meter element, and the
color input types.
Wednesday, April 1st, 2020
Working in a big organization is shocking to newcomers because of this, as suddenly everyone has to be consulted to make the smallest decision. And the more people you have to consult to get something done, the more bureaucracy exists within that company. In short: design systems cannot be effective in bureaucratic organizations. Trust me, I’ve tried.
Who hurt you, Robin?
Thursday, November 7th, 2019
Nolan writes up what he learned making accessibiity improvements to a single page app. The two big takeways involve letting the browser do the work for you:
Here’s the best piece of accessibility advice for newbies: if something is a button, make it a
<button>. If something is an input, make it an
<input>. Don’t try to reinvent everything from scratch using
And then there are all the issues that crop up when you take over the task of handling navigations:
- You need to manage focus yourself.
- You need to manage scroll position yourself.
For classic server-rendered pages, most browser engines give you this functionality for free. You don’t have to code anything. But in an SPA, since you’re overriding the normal navigation behavior, you have to handle the focus yourself.
Friday, October 4th, 2019
A deep dive info focus styles with this conclusion:
The default focus ring works. There are problems with it, but it can be good enough, especially if you can’t dedicate time and energy to create a custom focus ring.
Friday, December 7th, 2018
Designing your design process:
- Know your strengths and focus resources on your weaknesses.
- Learn to identify the immovable objects.
- What has to be perfect now and what can be fixed later?
Friday, April 20th, 2018
Patrick is thinking through a way to implement
:focus-visible that’s forwards and backwards compatible.
Friday, March 30th, 2018
A deep dive into the
:focus pseudo-class and why it’s important.
Wednesday, March 28th, 2018
Monday, November 20th, 2017
Instead of being prescriptive about error messaging, we use what the browser natively gives us.
Tuesday, November 1st, 2016
Rodney has done some great research into how different browsers respond to a focusable element becoming inactive (by being made disabled, hidden, or removed).
Tuesday, August 9th, 2016
A great series of short videos from Marcy on web accessibility.
Thursday, August 22nd, 2013
Double tap delay
Specifically, we talked about this proposal in Blink related to the 300 millisecond delay that mobile browsers introduce after a tap event.
Why do browsers have this 300 millisecond delay? Well, you know when you’re looking at fixed-width desktop-based website on a mobile phone, and everything is zoomed out, and one of the ways that you can zoom in to a specific portion of the page is to double tap on that content? A double tap is defined as two taps less than 300 milliseconds apart. So whenever you tap on something in a touch-based browser, it needs to wait for that length of time to see if you’re going to turn that single tap into a double tap.
The overall effect is that tap actions feel a little bit laggy on the web compared to native apps. You can fix this by using the fastclick code from FT Labs, but I always feel weird solving a problem on mobile by throwing more front-end code at it.
Hence the Blink proposal: if the author has used a
meta viewport declaration to set
width=device-width (effectively saying “hey, I know what I’m doing: this content doesn’t need to be zoomed”), then the 300 millisecond delay could be removed from tap events. Note: this only affects double taps—pinch zoom is unaffected.
This sounds like a sensible idea to me, but Ted says that he sometimes still likes to double tap to zoom even in responsive designs. He’d prefer a per-element solution rather than a per-document
meta element. An attribute? Or maybe a CSS declaration similar to pointer events?
I thought for a minute, and then I spitballed this idea: what if the 300 millisecond delay only applied to non-focusable elements?
After all, the tap delay is only noticeable when you’re trying to tap on a focusable element: links, buttons, form fields. Double tapping tends to happen on text content: divs, paragraphs, sections. That’s assuming you are actually using buttons and links for buttons and links—not
divs a-la Google.
And if the author decides they want to remove the tap delay on a non-focusable element, they can always make it focusable by adding
tabindex=-1 (if that still works …does that still work? I don’t even know any more).
Anyway, that was my not-very-considered idea, but on first pass, it doesn’t strike me as being obviously stupid or crazy.
So, how about it, browser makers? Does removing the 300 millisecond delay on focusable elements—possibly in combination with the
meta viewport declaration—make sense?
Tuesday, October 16th, 2012
Thoughtful points from Chris, delivered on the closing day of this year’s Brooklyn Beta.
So, the next time you feel like you’re missing out, stop it. Zoom out a little bit and give yourself some space and some perspective, so you can focus on what matters.