I’ve been asked again and again over the years what the absolute basics of web accessibility are. And while I always thought that it is not so difficult to find resources about these basics, the recurrence of that question prompted me to finally write my own take on this topic. So here it is, my list of absolute web accessibility basics every web developer should know about.

Alternative text for images

One of the questions I get asked the most is “which graphics require alternative text”? The answer to this question has three parts:

  1. All img tags require an alt attribute. This goes without exception. Everything else is an error. If you have an img tag in your HTML without an alt attribute, add it now.
  2. Every alt attribute has to have a value. And here is where it gets interesting. If the image is important, because it is part of an a tag, for example, it has to have meaningful text. What is a best alt text is still a point of sometimes heated debate, but the guideline is to use best judgement. Describe the image briefly, but avoid the phrase “image of” or “graphic of”. Because screen readers already know it is a graphic. In addition, every image that adds context to the text of a page that is important in understanding the text needs to have meaningful alternative text. If, on the other hand, an image is purely decorative, its alternative text consists of an empty string “”. That is simply alt=””, two consecutive quotes. But the alt attribute has to be there even for these decorative images, it must not be omitted.
  3. It is called alt attribute, alternative text, but never alt tag. alt is an attribute, not a HTML tag.

All the above also applies to SVG graphics. And if you’re really modern and use the picture element, the rules apply there, too.

Using proper alternative text does not just help blind and low vision screen reader users. It also helps on mobile where images sometimes cannot be loaded, for example over slow connections. So by implementing proper alternative text, you help many more people than you might initially imagine.

Labeling form fields

Another very common question I get, and a very common error I see on many many web pages even in 2015, concerns the labeling of forms and form fields. In fact, when dealing with many web developers, I am surprised that many don’t even seem to be aware that there is a label element, for example. So here are the most common rules about form field accessibility:

  1. Most input elements, as well as the select and textarea elements, need an associated label element that states the purpose. The one exception are those that produce a button, like the types of button, reset, and submit do. But every other, be it text, checkbox, password, radio (button), search etc. require a label element to be present.
  2. The association between such an input and label happens by giving the input a unique ID, given by the id attribute on the input, and the label’s for attribute, which points to said ID. To test that your label actually works, click on the label, not the input, select or textarea. Does the said element still get focus? If so, you did things right. This increases the click target for many audiences, including mobile devices where bigger touch targets are always advantageous. And it associates the label text to the input for screen readers unambiguously. Do not, under any circumstances, use the placeholder attribute as the label for an input element! Read here, why.
  3. Give button elements inner text, or if it needs to be a graphic, label it properly with alt text that corresponds to what a textual button label would be. See the section on alternative text for images above. Also, as recommended in the MDN article linked to, prefer button elements over html:input type=”button”, because it is more flexible for styling. Also, this is the go-to element if you have anything that is a div or span and that you want to make clickable with hundreds of kilobytes of JavaScript code. So before you do that, use button instead.
  4. A series of radio buttons go inside a fieldset element to group them together. The first element inside this fieldset is the legend element that contains the over-arching question or label for this group of choices.
  5. Fieldset and Legend should also be used if grouping together different sections of a bigger form for better readability. The fieldset element can take more than just radio button inputs.
  6. Label required fields by providing the HTML5 required attribute on the input as well as stating in the label that a form field is required. This can be done by either providing the word “required” as part of the label, or putting explanatory text at the top of the form telling users that fields marked with an asterisk are required. Do not denote required fields only by a different color. Screen reader users won’t be able to recognize those, and color-blind users, which are 8 percent of the worldwide male population, will also have a hard time finding these.
  7. Use appropriate input types for e-mail, URL, phone number etc. Mobile users will thank you because these will bring up the correct keyboards for the information asked. Also, it will make evaluation easier for you because the browser will immediately know if the correct information, e. g. a valid e-mail address, was entered. Modern browsers will do that, and if you need to support older browsers, they’ll automatically fall back to text, which is an appropriate fall-back.
  8. Make sure keyboard visibility is always guaranteed. If you see a frame appear around a form field when you click inside it, you should also see it appear when you walk through your form using the tab key on your keyboard. If it does not apear, check your :focus and :active stylings for these form fields in your CSS.

If you need something a little more fancy-looking, please do not fall back to using clickable span and div elements. Because if you do that, you’ll have to add roles, state handling, keyboard focusability and acting on key presses all by yourself. If you use form elements and help yourself with some span elements for styling inside the label, for example, you will get all the accessibility for free, including keyboard, screen readers etc.

Document structure

Believe it or not, but at its core, the web is a document-based structure. So even when we create fancy web applications such as Gmail, the heart of it is a document. And there is a lot you can do with documents semantically that will get you usually 80 to 90 percent of the accessibility for free. For example:

Heading structure

Noticed the different headings and sub headings in this blog post? Well, there are elements for that. They are called heading elements. And they give you exactly that, a six level heading structure to denote a main heading, secondary sub headings, and sub headings to those for sub sections, like this one, for example. This gives your document a logical, easy to follow structure. Have you ever wondered how Wikipedia puts together its table of contents for each article? They use the logical heading structure for that, too!The h1 through h6 elements are unambiguous in telling screen readers, search engines and other technologies what the structure of your document is. Do not mix unless the structure requires it, do not skip levels if possible, since that will disrupt the logic. And never ever again use something like a div with a class of “heading1” in your code. Screen readers, search engines, and other technologies will not know what to do with those. They will know how to treat your headings properly, though!


There are some more ways to structure your document’s contents. By landmarks, for example. Landmarks can be article, aside, footer, header, nav and main. Adding such landmarks appropriately can help further provide sense to your document and help users more easily navigate it.


HTML knows a whole bunch about lists. There are unordered and ordered lists that are exactly what you’d expect them to be. You can add numbering schemes, even nest them, and the browser will do the rest for you. You can style them the way you want them to look in CSS and thus provide even more structure and meaning to your document’s content. You’ve already seen ordered (numbered) lists in this blog post.

There is also a list type for definition term and explanation groups. The MDN page on the dl element has some great examples of use.


Did you know that HTML has an element to denote paragraphs? It is called the p element. For long citations that require their own paragraphs, use blockquote. For short, inline, quotes, use the q element. Visual separators can be inserted via the hr element.

For all these elements, use CSS to define indentation, separation between paragraphs etc. Those will not impact the semantics, but you are then free to adjust the visuals to your liking or your client’s requirements.


Tables are its own special case. So much can go wrong, and historically, so much abuse has happened to this poor table element and its sub elements! Especially layouts were done for a long time using tables, before HTML 4 and the onset of CSS. But I still find in modern web applications in 2015, cases where layout tables are being used to align form fields and their labels to one another. STOP DOING THAT! PLEASE!

The table element is a very useful element for creating data representations. Product detail listings, price lists etc. Also, shopping carts with quantities, sub totals and totals, and many other structured data collections can, and should, be put into data tables. Here are some tips to help you:

  1. Add a caption element to give the table a proper heading or summary.
  2. Use th elements to denote column and row headings. Make use of their scope and other attributes to clearly associate what belongs to which.
  3. Use other structural table elements denoted in the “see also” section of the table element documentation to further structure your table.
  4. If a table gets too complex or has multiple sections that don’t necessarily have to be in one table, split them up into several data tables.

For more information, I’d like to refer you to the friends at WebAIM who have put together a very good two-pager on the accessibility of HTML tables.

Some more quickies

Here are some more things you can quickly check and make sure when you write HTML, CSS and JavaScript.

Separation of concepts

HTML defines your content structure. It is what screen readers and other assistive technologies use to represent your content to their users.

CSS defines how that content looks visually. Its positioning, indentation, padding, margins usually have no bearing on what screen readers render to the user, with one exception: If display: none; or visibility: hidden; styles are used, that content will also not be available to assistive technologies. See my post titled “Hiding content untagled” for more information.

Also, CSS :before and :after text is rendered to assistive technologies. So be aware what you put in there.

JavaScript adds dynamic functionality. Its output must be proper HTML and CSS, too, if it manipulates the DOM. JavaScript dynamics in itself are no problem to accessibility, only some specific behaviors can be, like losing keyboard focus.

The clearer you separate the three, the more maintainable your code will be. Put CSS in their own files, don’t embed it in the HTML. Put JS modules in their files and don’t embed JS code in your HTML, either. This will make everything more readable, and remind you that the concepts should really be separate that just happen to work together rather than mingling uncontrollably.

Color contrast

Have you ever stood in the sunlight or another bright light source with your smartphone or tablet in hand and wondered why you couldn’t read something? Well, you were suffering from a lack of contrast between foreground and background on the page you were visiting. Low contrast ratios lead to bad readability in bright light situations. For the aging population, as well as low-vision users, low contrasts pose an even greater obstacle in readability. The Web Content Accessibility Guidelines define as a success criteria to have a contrast ratio of 4.5:1 on main content text to its background. You can use tools like the Colour Contrast Analyser to point at your content and see whether your visuals meet this requirement. Even if you’re not auditing for WCAG compliance, adhering to this rule of thumb is still a good idea for your own eyes as well as everyone else’s.

Keep Pinch alive!

When you develop for the mobile web, and today it is most likely you are, please keep the Pinch To Zoom gesture alive! Do not disable this gesture vital to many more of your readers than you might think! Pinching to zoom something small on a web page is very common and does not apply only to aging readers as well as those with low vision. If your layout does not cope with the pinch gesture for some reason, you need to revisit your responsive design and fix it. Do not disable the pinch gesture on mobile browsers!

OK, but what about advanced widgets?

If you really need to implement advanced widgets that are not indiginous to HTML, take good care that you implement all aspects of them. I have some information on how to make clickable widgets that should be buttons or links, tabs and tabpanels, some auto-complete widgets and modal dialogs accessible. The friends at SSB Bart Group have a quite current post on ARIA tree views up, and Terrill Thompson conducted an extensive test of ARIA menus.

It is all in the semantics

As you may have guessed by now, adhering to semantic structures that HTML already offers today will get you a long long way towards accessible web content. In fact, most web content that doesn’t need special widgets will most probably be over 90% accessible by just using proper semantics and honoring a few extras that are in styling.

Only if you need to use widgets that are not provided by HTML, will you really have to dig deeper and dive into standards like WAI-ARIA. But even its first rule is: Don’t use it if you don’t have to! Just sugar-coating everything with WAI-ARIA attributes you find in Google somewhere will do more harm than good. I promise!

In conclusion

If there’s one wish I have for Christmas from the web developer community at large, it is this: Be good citizens of the web, and learn proper HTML before you even so much as touch any JavaScript framework. Those frameworks are great and offer a lot of features, no doubt. But before you use hundreds of kilobytes of JavaScript to make something clickable, you may want to try if a simple button element doesn’t do the trick just as fine!

Use semantics and save yourselves a lot of extra work, because all the standard elements come with accessibility for free.

Teach others! If you’ve mastered the skills of a good HTML and CSS citizen, teach others! Get involved, contribute your knowledge and share your wisdom! You’ll help at least two more than the obvious ones with every contribution you make!

I hope this article helps a little to clarify how easy it is to gain way over 80%, if not over 90% of accessible web content just by following standards and semantics! Please feel free to share your thoughts in the comments below, and if there is something I missed that you think should belong in this collection, feel free to also let me know, and I’ll add it!

Thank you!

This topic is also available as a video presentation held at the 2016 Global Accessibility Awareness Day’s Inclusive Design 24 event.

In recent months, I’ve started using the IRCCloud service for all my communication via Internet Relay Chat (IRC). We use IRC at Mozilla, and many other open source projects as well as the W3C use IRC for their instant communication needs.

Previously, I had been using typical IRC clients such as Adium for OS X or ChatZilla as an add-on to Firefox. But that caused a lot of problems when working from multiple machines, like not being able to easily switch fron one to the other without losing and having to rebuild context, or logging in with two separate nicknames etc.

A while ago, IRCCloud started appearing at the peripherals of my filter bubble. It is a cloud-based IRC client with a few extras. And in the spring, I decided to finally check it out myself. We’re running an instance of the Enterprise Edition at Mozilla. So I got an account, and off I went.

What is it?

Here is what the team says about the service. IRCCloud is offered as both a web application and native apps for iOS and Android. The native apps offer push notifications for nickname mentions as well as keyword highlights, meaning one can react to things even on the go without sitting in front of the computer. IRCCloud comes in two flavors: One instance that is hosted at irccloud.com, which allows individuals and teams to connect to IRC via IRCCloud’s hosted service, and the Enterprise Edition, which is usually self-hosted by the organization purchasing the annual subscription. The latter is what Mozilla is using, but I have been looking at both instances by now, since they differ slightly. The instance at IRCCloud itself is usually newer, has the latest and greatest features, while the Enterprise editions can lag a bit behind.

IRCCloud works like this: You log onto the service, and from there, manage your different IRC server connections with nicknames, registered nick passwords etc. The paid accounts offer you an unlimited number of connections. The free edition allows for two except the one to irc.irccloud.com. The Pricing page has more information and details.

Once connected, the connections are permanent. IRCCloud keeps you logged into all your IRC servers and collects incoming chats even when you are currently not logged into the IRCCloud service. But when you come back, either through the web site or mobile app, you can review everything that has happened in your absence. This includes private messages that wait for you just like on any other instant messaging service.

The accessibility

When I first started using our Enterprise instance, I found the web application to be very accessible. All the options were easily reachable with the NVDA virtual cursor in Firefox, or also Safari or Chrome + VoiceOver on OS X. IRCCloud supports the standard IRC commands that start with a slash / character. The entry happens in a standard multiline text area, the output in a part of the web page right above that text area. Adding servers, channels and starting private conversations were all manageable through controls present on the web page. Also the nice additions like paste bins for multi-line text, uploading of images, embedding of tweets etc. all worked nicely.

However, with a redesign in September of 2015, the web app hosted on irccloud.com lost some of this accessibility due to things now being hidden behind mouse hovers, or elements turning from semantic links to non-semantic text clickables. At first, I didn’t make the connection, but at some point it dawned on me that, if Mozilla pulled in these changes at some point, I and other current and future visually impaired or blind Mozilla employees would lose that functionality as well. So I decided to contact the IRCCloud team.

Over the past week or so, I worked with James, one of the founders of IRCCloud, who works on the front-end portion, to resolve the (for me) most urgent issues in the IRCCloud instance. This is already live, and anyone can try it out. The things we covered were:

  • Clickable text that should be buttons were made buttons via WAI-ARIA.
  • Those items that expand to a multitude of options such as the account e-mail address or the Options buttons, indicate their states via aria-expanded. Those that open to a non-modal pop-over such as every nick name anywhere in chats and private messages, will have a sub menu indicator. Those sub menus aren’t really sub menus, but rather pop-overs with a multitude of options such as being able to directly send a private message, finding out who that person is etc.
  • The channels and servers as well as each private message nickname are now announced as tabs. This seemed to us the most appropriate mapping, since only one channel, server output or private message is usually visible at a time, but radio buttons didn’t seem really appropriate to use. James kept the heading structure in place, so that every server instance starts with a new heading.
  • Things that were previously hidden behind mouse hovers such as the Options button for an individual IRC server entry are now shown when the server name is focused via the virtual cursor or other browsing mechanism. With NVDA, this will cause the virtual cursor to land on the Options button once the button becomes visible, with the server name moving down one line in the virtual buffer.
  • Options in the individual server settings, accessible from the above mentioned Options button, are now toggle buttons if they are toggleable. Other buttons remain normal buttons as appropriate. But now, the state is clearly communicated whether an option such as embedding social links etc. are on or off.
  • In channel views,  if there is a series of status messages that are collapsed, the button to expand these into individual entries is now accessible, and it indicates whether the status messages are currently expanded or collapsed.

This is by far not meant as a full audit, nor was it meant to be a full consulting service. I pointed out to James the most low-hanging fruits that made working with IRCCloud difficult for me after the redesign. James was super responsive in adding the appropriate attributes and also adding his own ideas and asking good questions about details here and there. What we did not at all tackle, were issues for keyboard-only, non-screen reader users or low-vision users. I do not, for example, know if contrast is good in all places. But what we did can certainly be viewed as a starting point for dealing with other issues that might cause headaches for some users. Interest and willingness to fix these issues is definitely there, so don’t be shy if you want to use IRCCloud and run into problems!

The iOS app

Even before working with James on the web app, I contacted the team with some problems I had found in the pre 2.0 version of the iOS app. The iOS app had, for example, a problem with not updating VoiceOver content with the new loaded content after switching channels. However, since buttons were labeled and other attention to detail had been given, I was sure this was only an oversight. Sam, the IRCCloud team member responsible for the mobile apps, came back with a very fast response, and we worked together throwing back and forth observations and new beta builds, and within a day, in time for the recent 2.0 release of the iOS app, the problems were solved and some more improvements were made. Now, the iOS client which runs on both iPhone and iPad is very accessible. In fact I am not aware of any area of the app right now that I cannot use.

Wait, what about the Android app?

Sorry, I didn’t look at that one. I currently use Android only for testing Firefox, not as aproductive device of any kind, so looking at that had no priority for me among all the other things I have to take care of in my day to day job at Mozilla.

What about Slack or Gitter?

Gitter is a chat service built around the Github eco system and is very developer-centric. Its accessibility on the web is limited, and I know nothing about the iOS or Android apps. It offers an IRC bridge, so one can interact with one’s rooms on Gitter via IRC.

Slack is also an enhanced chat service that offers team collaboration and embedding of many kinds of media, file transfers etc. I tested Slack when I wanted to join the a11y Slackers, but was very unhappy with the service. The web service is all non-semantic clickables. The iOS app seemed to have a problem in that it showed me the chat history in a seemingly random order. As I only found out much later, the Slack iOS client has a twist that isn’t immediately obvious, but it is accessible. I ended up using the Gitter to IRC bridge and my Mozilla-hosted IRCCloud instance to connect to it and am now always-on there.

Both these services are centralised, proprietary messaging services unlike IRC, which is an open, distributed system of different networks that don’t depend on one another. So even when IRCCloud should suffer an outage, not the whole system becomes unavailable at once, and you can always use an alternative client as an emergency backup to connect to your favorite IRC servers. IRCCloud does offer additional features like file storage, embedding of social links, pastebins and (if you want to) videos, bringing it up to the level of other proprietary solutions. And some parts of IRCCloud are even open-source!


Some might think that this post contains a lot of information that could be conceived as marketing. I am not associated with IRCCloud in any other way than that I use their service, and I do not receive any compensation for writing this post. This post purely reflects my own opinion about their service. Their responsiveness to accessibility issues and fixing them in a speedy fashion is commendable. I like this service, that’s all. 😉

And I hope this post helped you in understanding it a little better and maybe trying it out yourselves! After all, you never know what happens to some other IRC clients in the future. With some major changes coming to Firefox next year, the ChatZilla add-on may be rendered unusable for some time, for example. So it’s always helpful to know about accessible alternatives.

Have fun exploring! And happy chatting!


  • 11-01-2016: Updated my statement regarding the Slack iOS client.