Over the years as a front-end developer, I have picked up a few basics for building accessible websites that have become an integral part of my daily workflow. These techniques give me a solid foundation for building an inclusive website that is welcoming to all, and they help me write cleaner and more performant code.
Following is a list of some of the things that I do on every website without fail.
1. Use semantic HTML markup
Semantic HTML is at the core of creating an accessible website. It takes the DOM tree and turns it into the accessibility tree which helps machines, including assistive technologies and search engines, understand the content and the structure of the page.
My favorite example is the case of buttons. Using the semantic button element instead of a <div>
or a <span>
, gives you most of the accessibility goodness right out of the box without having to write a lot of extra code.
A <button>
gives you things like focus handling, user input handling, form submission, and some basic styling that can be exposed to the accessibility API. On the other hand, using a custom button element means you would need to write additional code, most likely using JavaScript, to make your custom element functional. And, you will have to include additional attributes in the markup such as role
and tabindex
to make it accessible for keyboard and screen reader users.
Take a look at this div marked up as a button:
<div
class="button"
role="button"
onclick="runThatFunc()"
onkeydown="runThatFunc()"
tabindex="0"
>
Submit
</div>
In this example, you need to add the role
, tabindex
, and a keydown event to make sure that div is going to behave like an accessible button.
Now consider a semantic button element:
<button
class="button"
onclick="runThatFunc()"
>
Submit
</button>
When you use an actual <button>
, all you need to do is attach a function that will do a thing when someone interacts with this button and you’re done. That’s three less things you need to worry about to make it act like an accessible button that will work equally well with a keyboard and a mouse.
2. Create a logical heading structure
Headings can be an important navigational tool for users of assistive technology. According to WebAIM’s Screen Reader Survey for 2018, nearly 70% of people use headings to navigate content and over 52% of the people find heading levels useful for finding information on the page. Just as visual users can quickly scan the page to understand the hierarchy of the content by looking at the headings, screen readers allow users can listen to a list of headings on a page and start reading from one they are interested in.
There should be at least one <h1>
per page to convey the overall purpose of the page followed by <h2>
to <h6>
in a sequential order. New sections can begin with headings of equal or higher rank, and within each section headings of smaller rank can be used for starting subsections.
Avoid skipping heading levels within a section as the resulting content flow can be confusing for a user navigating by headings. This means, an <h2>
should never be followed directly by an <h5>
. However, you can use an <h2>
to start a new section after an <h4>
has been used in the previous section.
Finally, a heading element should never be used just for stylistic purposes. There’s CSS for that! If the content doesn’t make sense as a headline, it should not be contained in a heading tag.
3. Include text alternatives for images
The internet is full of images that make it a rich and exciting place, and sometimes also provide functional information. It can be very frustrating for some users if they land on a page and are unable to see or hear some parts of it, especially if that information is needed to perform an action on the site.
Including useful text alternatives on images can let users with low or no vision understand the content better. Every image must include an alt attribute with a description of exactly what the image is representing. Screen readers announce images as images, so your alt text does not need to start with “Picture of ” or “Image of” as that would be redundant information.
In case of decorative images that do not contain any valuable information for the users to understand the content, an empty alt text (alt=“”
) can be used. However, an alt attribute must always be present even if the value is null.
Any functional or informative images such as social media icons, accepted credit card logos, help icon, search icon etc. must have text alternatives that describe the purpose of the icon.
If the icon is included as an image within a link, you can use the text of the link to convey the purpose along with an empty alt text on the image.
<a href="website.com">
<img src="logo.jpg" alt="" >
Website Name
</a>
Or, you can use the alt text on the image to let the user know where the link goes if no visual link text is used.
<a href="website.com">
<img src="logo.jpg" alt="Website Name" >
</a>
Got text within an image? Scrap it! Images with text within them are problematic for screen reader users as assistive technologies would not be able to read that text. If you can, include that text as part of the content on the page. However, if the image of text is unavoidable, then that exact text should be included as alt text on the image.
4. Label form fields
Labels help identify a field for screen reader users when they are interacting with it. Use the <label>
element to label your form fields and programmatically connect it to the form control using the for attribute.
<label for="email">Email address:</label>
<input type="email" id="email" name="email">
You might think that using a placeholder instead of a label is sufficient as it provides a visual cue for what information is requested. However, placeholder text can be problematic for both visual and non-visual users. The placeholder text disappears when a user starts typing in the field and even visual users can sometimes have trouble identifying the purpose of the input if no label is present.
In addition, screen reader users can find it frustrating as the placeholder attribute does not always get announced because of inconsistent support across browsers and screen readers.
If a field has been designed without visible labels and for whatever reason there is no way you can have that changed in design, the markup should still include a visually hidden label that is associated with the field.
There are a lots of different ways for visually hiding elements on a page using CSS, however not all of those ways are equally accessible. If you want your content to be visually hidden, but still available to screen reader users, you have to be careful not to use display: none;
or visibility: hidden;
as both those properties will hide the content from screen readers. Instead, you can hide the content only for visual users by using the clip property in CSS.
Here is a snippet that will cover most of the basic scenarios where you might need to make an element only available for screen reader users:
.show-for-sr {
position: absolute !important;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0,0,0,0);
}
Form controls that are related, such as a list of checkboxes or radio buttons, should be grouped together with <fieldset>
. They can be given description using the <legend>
element to provide more context for users of assistive technologies. Some screen readers will read out the legend with each choice, so a user doesn’t just hear the option such as “Lightsaber” or “Sonic Screwdriver” in the example below, but they will also hear the question that the option is associated with.
<fieldset>
<legend>Choose your weapon:</legend>
<input type="radio" id="lightsaber" name="weapons">
<label for="lightsaber">Lightsaber</label>
<input type="radio" id="sonic-screwdriver" name="weapons">
<label for="sonic-screwdriver">Sonic Screwdriver</label>
<input type="radio" id="baguette" name="weapons">
<label for="baguette">Baguette</label>
<fieldset>
If you got all the way to the end of this post, thanks for reading! I hope you find these tips useful and will incorporate them in your work.
Have a question? Feel free to ask in the comments below or on twitter.
Top comments (0)