Five Goofy Things Medium Did
That Break Accessibility
Medium Engineering recently had an accessibility fixit. We found some goofy things! But we’re trying to do better. We wanted to share some of what we found.
1 DON’T: “Intercept” clicks by creating a transparent overlay over a control.
This pattern made the home page completely unreadable on screenreaders. Every stream item had an overlay. The screenreader would try to read the overlay, instead of the content in the item. If you’re trying to “trick” the browser into doing something non-standard on mouse click, please be mindful of how your trick will look to screenreaders.
DO: We have a web-client guild! With office hours! If our engineers want guidance on how to support non-standard interactions on click, we ask them to come by and talk to us. With streams, we made the whole item into a link.
2 DON’T: Use opacity: 0 to hide elements.
Web browsers support many ways to hide elements — display: none (“hide and set width/height to 0”), visibility: hidden (“hide but take up the same space”), and aria-hidden=true (“screenreaders should ignore this”). Many of these are well-supported by modern screenreaders (See Footnote 1).
But using opacity: 0 to hide things is well-supported by no one. We used to do this for fade-in/fade-out animations.
DO: Whenever you set opacity, also set visibility. We now have LESS mixins .m-fadeIn and .m-fadeOut that help do the fade-in/fade-out use case correctly. They look like this:
.m-fadeOut {
visibility: hidden;
opacity: 0;
transition: visibility 0s linear 300ms, opacity 300ms;
}
.m-fadeIn {
visibility: visible;
opacity: 1;
transition: visibility 0s linear 0s, opacity 300ms;
}
3 DON’T: Create an <a> tag without an href
We used to make anything clickable into an <a> tag, so that it would get all the CSS styles of a link. But screenreaders expect links to … link to things.
DO: We now have two closure templates for this: a views.ui.links for stuff with hrefs, and a views.ui.buttons isLink for stuff without an href that looks like a link. Anton made an effort to simplify the API and make the two look the same even though they have different HTML structures.
4 DON’T: Create a button or link without text.
Many of our buttons and links use webfont-based icons. They’re pretty! But the screenreader doesn’t know what they are.
DO: When using an icon or image, we have a template that requires a text description. The template will do its best to do the right thing, setting “title” and “aria-label.” (See Footnote 2)
5 DON’T: Attach actions to SPAN or DIV tags to listen for user input.
We have a framework to listen to actions whether they’re triggered by a click or a touchscreen or a keyboard. We add an HTML attribute data-action=“recommend”, and the system automatically attaches handlers. But this API was so successful that engineers starting slapping data-action on anything, even random <span> tags. Screenreaders don’t know about data-action, and won’t know that this is clickable.
DO: Use <button> tags for all clickable controls.
Bonus Trivia
We’ve also made some other notable changes the past two weeks that help with accessibility.
Headers and Footers — Accessibility people are big fans of semantic markup like <header>, <footer>, and <nav>. Koop noticed that our post pages had become a “sheer insanity” of nested containers.
<div class="postArticle">
<div class="postWrapper">
<div class="postWrapper-inner">
<div class="postContent">
<div class="postContent-inner">
<div class="notesSource">
<div class="postField">
// Finally display the post.
He cleaned things up to a much simpler <header><div role=“main”><footer> that’s much easier to parse.
role=“menuitem” — Most of our popovers are menus. We’re still trying to figure out the best template API for doing this well. We added some code to so that if the popover has buttons or links marked role=“menuitem”, the up/down arrow keys will navigate through them.
Footnote 1) Fun fact: how to hide elements in a screenreader-friendly way is surprisingly controversial. Some people say that display: none should be enough. Other people say that some versions of JAWS (the most popular screenreader) have a bug and the recommended workaround is to use visibility: hidden and display: none together. Other people say screenreaders can’t be trusted to interpret CSS, so we should abandon CSS and use DOM attributes for everything. O.o
Footnote 2) Fun fact: how to add screenreader-friendly text is also controversial, also because of bugs. Some screenreaders won’t read “title” attributes (or only do if you opt-in). Others won’t read “aria-label” attributes. Others recommend that you create a span with text-indent: -999999px to position the text offscreen.
There are many blog posts on this. They mostly make me depressed about the state of accessibility tools.
There are still many more things to fix!
What do you hate most about Medium’s web accessibility? What anti-patterns do you wish people would stop doing? Let us know in a response or by emailing yourfriends@medium.com.