Some do’s and dont’s we gathered from making the Firefox OS UI more accessible

In my last post, I mentioned that we learned a few things from making the Firefox OS UI, code-named Gaia, more accessible over the past few months. This produced quite a few questions about what these things were. So rather than adding them to that blog post, here’s a dedicated one to just that topic.

First, a big thank you to Yura and Eitan for their input on this. It is mostly their patches that I learned these things from, I only played with some of the code myself and gave up when I was notified how much of the CSS broke by my code changes. :)

Use buttons or links, not clickable divs and spans

Should be pretty obvious, but you would be surprised at how many clickable divs and spans there can be inside a single web app. Why that is, escapes me really. And despite what Google’s accessibility evangelists say in their videos, the rest of the accessibility community agrees with me that clickable spans and divs instead of buttons or links are not good practice!

Especially buttons are no longer hard to style to one’s liking nowadays. Moreover, buttons are focusable by default, they respond to the “disabled” attribute and are taken out of the focus order, and you get the onClick mechanism for free that usually responds to mouse, keyboard and touch. Moreover, if you just add the type=”button” attribute to a button element inside a form, it no longer is a submit button.

Second preferred thing should be links, however links don’t respond to the disabled attribute and may be harder to style. But there are places where they are definitely the appropriate thing to choose and should not be replaced by anything else.

Don’t use WAI-ARIA roles in CSS selectors

Although technically possible, this is extremely bad practice in our experience. First, WAI-ARIA markup has a very specific purpose. it is there to make HTML elements accessible to screen readers when these are used in a way they were not originally designed for. An example are tabs. HTML has no tabs widget, so compound HTML blocks must be used to simulate them. There is a very specific path to follow for these. If CSS selectors were now based on that markup, and that markup needs to change, suddenly a whole bunch of CSS needs to be touched to, or the layout will break.

In our case, WAI-ARIA roles had been inserted without actual knowledge of what they were meant for, and CSS selectors were based on that. Moreover, other parts of markup then used those CSS selectors by making simple rows of buttons inherit some of the tab styling, which made those buttons expose totally inappropriate semantics to screen readers.

So whatever you do, do not use WAI-ARIA roles or attributes as selectors for your CSS. Keep the visuals clearly separated from the screen reader-intended markup!

Hide inactive content properly

If your app is made in a way where every screen gets its own HTML page, you’re out of the woods. If, on the other hand, several screens are put within one HTML file, you need to absolutely make sure that content is hidden properly. Like the sighted user, you want to trap the screen reader user on one particular touch screen at a time. All touch-screen-supporting screen readers support a sequential method of going through available items on a screen. If you don’t hide the inactive/invisible parts of your app from the screen reader user, they are now suddenly able to move to parts you don’t intend them to go. They might even try to activate items in parts that are currently not appropriate, potentially breaking your app’s logic. We found three methods to work best when hiding content:

  1. Use styling like display: none; or visibility: hidden; for those parts you don’t want shown. That is the most reliable method to hide content, since screen readers don’t ever expose such content. There is a more thorough explanation of the mechanisms and things to consider is described in another post on this blog.
  2. If the above does not work for you for some reason, because you may encounter performance or reflow issues, resort to using aria-hidden. Hide everything except the active screen.

Use common accessibility practices

Most accessibility practices you’ve learned for desktops also apply for mobile. Use alt text, or if that doesn’t work out for some reason, aria-label for images, form labeling techniques as usual, and make sure you have a logical order of your HTML, because on mobile, too, screen readers infer the reading order from the order of the elements in the document object model.

As if on queue, the BBC accessibility team have published their mobile accessibility guidelines today. And although tailored towards the BBC primarily, all of the techniques and examples found there are valid for any mobile web app and its accessibility. I strongly recommend you check them out! If I was your teacher, I’d say: Mandatory read! :)

6 comments:

  1. You say you found three methods that work best when hiding content, but I see only two. Is the third method hidden or what??

  2. This is a great post highlighting a lot of important a11y basics for developers, but I’d like to discuss the following:

    “So whatever you do, do not use WAI-ARIA roles or attributes as selectors for your CSS. ”
    This is a pretty strong blanket statement on how to write CSS. I agree that generally, styling should be kept as independent as possible from un-related markup, but I think in some cases, it can make sense to link visual styles to Aria attributes if you isolate the styles properly. In the case of a tab for example, I think the following makes sense:


    .tab-panel[aria-hidden="true"] {
    display: none;
    }

    .tab-panel[aria-hidden="false"] {
    display: block;
    }

    This serves both as a “reminder” to developers to update Aria attributes when a new tab panel is selected (as they serve as a styling hook), and simplifies JS since otherwise it’s likely an extra class would have to be added dynamically just for the styles. I agree that you can get into trouble if you start extending these styles elsewhere, but I think it’d be more of a symptom of developer ignorance if all of a sudden someone started applying Aria-roles simply to apply display: block to an element.

    Sweeping statements like this may dissuade valid discussion and place “rules” over experience and testing. If this really is a bad practice, showing examples of how it can fail specifically would be more useful (albeit that’d probably be a topic for its own separate post). Anyways thanks for the post, a great real-world overview of common considerations!

    1. Thanks for your comment, Monika! Your example is actually one for another blanket statement: Don’t use aria-hidden, you don’t need it here! The example you gave works perfectly without aria-hidden. It is a superflous attribute that does more harm than good here. I suggest to read up on my Advanced ARIA Tip #1 about tabs, and also the “Hiding content untangled” post. :) My general advice is: avoid aria-hidden whenever possible.

  3. Fair enough, and I see your point about aria-hidden being superfluous in this case. Having read the Aria Tip #1 article though, for argument’s sake, couldn’t the following be used as an example of Aria in CSS selectors to style the active tab button/link to distinguish it from the others?


    .tab-button[aria-selected="true"] {
    background: #specialActiveColor;
    }

    It’s a much more trivial example now, but still something that might be useful especially if we don’t have to add an extra styling class via JS now. Anyways, just something I thought was worth considering. Thanks for your response!

  4. When you say, ~“Don’t use ARIA in CSS”, I read, “Don’t hire an engineer that would stab together markup without understanding what it’ does.”

    I have to agree with Monika here. Using ARIA in CSS (especially for toggle state styles like the @aria-selected example) are a perfect use of semantic markup, and CSS excels at styling that semantic markup. It prevents classitis and code duplication, because without it, you’d need to toggle a classname and an ARIA attribute.

    Your problem wasn’t ARIA in CSS; it was an engineer who used semantic markup incorrectly in order to achieve a visual style.

What are your thoughts?