Improving website accessibility for screen readers (part 1)

About 300 million people experience some sort of visual impairment. Unfortunately this is often overlooked by developers and product owners. The good news news is that it is easy to get started on improving your website. Making your website accessible means your website potentially reaching a wider audience and more easily retain traffic from people these impairments.

An accessible web page will typically also rank better in search engines such as Google. More on that later.

In this tutorial series I will explain why you should make your website accessible. I will also go through the basics of implementing ARIA as well as provide some basic accessibility tips.

Why should my website be accessible?

  • You may be missing out on visitors. Your website will better retain traffic from people who (for whatever reason) cannot read the screen content themselves. By catering your website to screen readers you help make the internet a little bit easier to use for people in need of assistive technologies.

  • SEO Accessibility may not explicitly be something Google looks at in terms of ranking websites in their index. However, the same elements, properties and states which improve accessibility also help out web crawlers and spiders. It helps Google and other search engines to better understand and categorize the content of your website.

  • Business or legal requirements Some clients may have a legal requirement to provide information in an accessible manner. The Americans with Disabilities Act (ADA) requires state and local governments in the United States to make their websites accessible. Most other countries have similar regulations.

Following the completion of the HTML5 specification on the 28th of October 2014 more expressive and semantic elements were introduced, such as article and nav. These elements make it easier for assistive program such as JAWS to make more sense of the web page.

In addition to these new elements in HTML5 the W3C also released a technical specification called Accessible Rich Internet Applications (ARIA for short):

“WAI-ARIA is a technical specification that provides a framework to improve the accessibility and interoperability of web content and applications.”

Most screen readers are used together with speech synthesis software to interact with blind or partially blind users. It may also be used together with a refreshable braille display to interact with deaf and/or blind.

Part 1: Forms and labels

In this first part of the article series I will show you how to apply these practices to a form. The ARIA attributes are not limited to forms and may be used on just any applicable web component. For a complete list of attributes and element combinations you should check out the chapter Document conformance requirements for use of ARIA attributes in HTML of the ARIA specification.

This is the code for a simple contact form with some of the ARIA attributes applied. It is supposed to illustrate what a submitted form with invalid input data may look like.

<h1>Contact form</h1>
    <label for="name">
      <span aria-hidden="true">*</span>
      Your name:
    <input id="name"
    <span role="alert" id="name-error">
      Your name cannot be empty.
    <label for="email">
      <span aria-hidden="true">*</span>
      Your email address:
    <input id="email"
    <span role="alert" id="email-error">
      Your email address is invalid.
    <label for="phone">Your phone number:</label>
    <span id="phone-description">
      Please enter your phone number including your country dial code.
    <input id="phone"
    <label for="message">
      <span aria-hidden="true">*</span>
      Your message:
    <textarea required id="message"></textarea>
    <label for="reason">Reason:</label>
    <button type="submit">
        Send message

This is a pretty straight forward form but some things may be unfamiliar to you if you have not worked with web accessibility before.

Read on to learn more about the attributes, roles and HTML elements.

The attributes: aria-describedby and aria-labeledby

While the attributes aria-describedby and aria-labeledby are closely related they serve different purposes: aria-describedby takes the ID of an element which describes the element more in detail while aria-labeledby takes the ID of a label that shortly describes the element (such as a header).

In the form we earlier used the two elements in this way:

<input id="email"
  <span role="alert" id="email-error">
    Your email address is invalid.

The attribute aria-label may also be used but only when the label text is visible on the screen. You may have a close button by using the upper case character X. Maybe you are using Font Awesome. Neither of which convey a clear and semantic label of the button.

In both of these cases the aria-label attribute may be used as such:

  <button aria-label="Close">X</button>

Or like this with Font Awesome:

  <i class="fa fa-times" aria-label="Close"></i>

If you are using an icon from Font Awesome only for cosmetic purposes then you should tell screen readers to ignore the icon by using the aria-hidden attribute as such:

The roles: alert

The alert role is supposed to be used when you want to catch the user’s immediate attention. It could be added dynamically and will in fire an event to the screen reader and alert the user. This role is typically used when you want to notify users of errors in a form. It could also be used to warn about a session which is about to expire.

To dynamically create an alert you use can use plain JavaScript or a library such a jQuery. Simple insert the element into the DOM.

  $("<span role='alert'>Your passwords do not match.</span>")

To add the role to an existing element you set the attribute role. In jQuery it looks like this.

  $("span").attr("role", "alert");

Alerts must be visible or the screen reader software will not detect it. The CSS property display may not be set to none. Nor may the property visibility be set to hidden.

The elements: labels, inputs, fieldsets and legends

These elements (and their different types) are common in HTML forms and should be used where applicable.


The label element the single most important element for accessibility. As it is directly responsible for describing input fields this is a must when creating forms.

When an input element is focused by the screen reader it will read the associated label to the user. The label may wrap the input it is describing. If it is not wrapping you need to use the for attribute which should contain the identifier for the input it is describing.

  <!-- Wrapping the input -->
  <label>Your name <input type="text"></label>

  <!-- Using the for attribute -->
  <label for="name">Your name</label>
  <input type="text" id="name">


In HTML5 several new input types were added to improve semantics and allow for better form validation. They also convey a better message to screen readers. As an example they may let the reader now a date input is selected and using the Up arrow may select the next month.

Compare this to using an old fashioned text input without any date semantics attached. The user would not as easily figure out how to set the date.

Input How screen readers may announce the input
<input type="color"> Choose a color. Edit. Type in text.
<input type="date"> Edit. Spin box. Blank. To set the value use the arrow keys or type the value
<input type="email"> Email address. Edit. Type in text
<input type="file"> File. Upload. Edit. Enter name of file to upload. “File upload edit. Browse…”
<input type="image"> Submit. Button
<input type="password"> Password. Edit. Type in text
<input type="range"> Rate the movie. Left right slider. 50. To increase or decrease use the arrow keys
<input type="search"> Search. Edit. Type in text Note: “Search” is the contents of the label.
<input type="tel"> Phone. Edit. Type in text
<input type="text"> Name. Edit. Type in text
<input type="url"> Website. Edit. Type in text

Fieldsets and legends

Fieldsets and legends are also important. Screen readers will often read the legend before proceeding to any of the other form content. Fieldsets and legends are used primarily in more complex forms which you may want to break up into multiple sections.

  <label for="card_type">Credit card type:</label>
  <select id="card_type">
  <label for="card_number">Credit card type:</label>
  <input id="card_number" type="text" pattern="[0-9]{13,16}">

Avoiding redundancy

HTML elements such as nav, button and a implicitly have a clear and defined meaning to web browsers: the element nav is used in site navigation, button represents a clickable button and the a element represents a link.

If you are using a modern screen reader in combination with a somewhat modern web browser you do not have to supply a role if the element already has a default role attached to it. In fact the specification explicitly recommends not to do so.

Setting an ARIA role and/or aria-* attribute that matches the default implicit ARIA semantics is unnecessary and is not recommended as these properties are already set by the browser.

If you developing a website which needs to be supported by outdated browsers you may want to take the safe route by adding roles even if they are implicitly added. You may want to take a look at the list of browsers (and browser versions) Mozilla published which support ARIA out of the box.

JAWS has been supporting ARIA (with support for live-region and alerts) since version 10 which was initially released in 2008. Realistically you should not need to take these legacy versions into consideration when developing unless you have a very specific reason to do so.

This is a list of the most common form elements and their respective ARIA roles.

HTML element Default ARIA role (and how screen readers see them)
<form> <form role="form">
<img alt="Must not be empty"> <img alt="Must not be empty" role="image">
<input type="button"> <input role="button" type="button">
<input type="checkbox"> <input role="checkbox" type="button">
<input type="email"> <input type="email" role="textbox">
<input type="password"> <input type="password" role="textbox">
<input type="tel"> <input type="tel" role="textbox">
<input type="text"> <input type="text" role="textbox">
<input type="url"> <input type="url role="textbox">
<textarea> <textarea role="textbox">

Final words

I initially planned to write all about web accessibility in one single post but it quickly grew in size. I consider this an important subject so leaving out information did not feel like a good option.

In part 2 I will talk about navigation menus, dialogs and buttons.

Thank you for reading. Please leave feedback in the comments section.

Further reading

  • maxdesign: Accessibility tests
    This is an interesting read if you like to know more about exactly what is spoken to the users. You may install a screen reader program and try it out yourself.