Foreword
You can find many articles talking and describing accessibility for the web. Most of them are just discourse or they're aimed to cover specific aspect. There's nothing wrong with that since this is a very wide topic. However, when it comes to "implement accessible website or web-app" or "get the job done" I couldn't find any step-by-step instruction telling me what to do to make this happened. This article is aimed to help you build an accessible website or web-app by providing a list of TODO's. You can read brief intro paragraphs (the story, what is accessibility, etc.) or jump straight to each requirement and start to implement it.
The Story
A while ago, I needed to refactor a website due to an absence of the accessibility. For a lot of developers, term accessibility is a rocket science and I wasn't an exception. It requires a meaningful amount of time to research and understand all ideas around it. It is also really difficult to check whether your implementation is right or not. I faced a lot of issues that are either partially explained or not described at all. I went through the unknown way of specific HTML rules and attributes, trough the heavy battle with UI designers and through the bugs I didn't expect to see. In this article, I would like to share how we can make websites accessible in the easiest way possible by applying a set of HTML laws with a help of CSS and JavaScript. But first of all, let's define what is accessibility from the web perspective.
What is accessibility?
Accessibility is a practice to make sites usable for people with impairment. Most of the time when we use term "impairment" or "disabilities" on the internet we mean blindness. However, there are other types of impairment: visual (not only complete blindness but also color blindness, visual impairment), auditory, physical, cognitive. In this article, most of the time I will use examples for blind people. Nevertheless, I'll also cover accessibility techniques for other types.
Small note: You may also find a term "ADA Compliance" where ADA stands for "Americans with Disabilities Act". In this context, I'll use it with the same meaning as "Accessibility".
How many people are affected?
Research of the October 2017 shows that 283 million people are estimated to be visually impaired worldwide: 36 million are blind and 217 million have moderate to severe vision impairment source. If we will take into account that in 2017 the planet was inhabited by 7.6 billion people, we can calculate that ~3% of all population have the visual impairment. It's a huge number, considering that our population always grows and there would be more people affected by this. In addition to that, this case doesn't highlight the people with other disabilities like auditory, physical, cognitive.
Why do we need to make sites accessible?
- Satisfy existing, get new clients and increase the audience. Let's assume that you have a product that is being used by a handicapped person. This might be already existing customer or somebody who just started using your software. If you would not create an accessible option, he or she will complain about your product or just find a better alternative that supports assistive technology.
- Boost user experience. Even if a small part of your audience can't leave home due to their physical abilities, you can make them happier by providing enhanced shopping experience.
- Benefits for people without disabilities. In some cases, it's way faster and more convenient to navigate through the site by using keyboard only.
- SEO Improvements and meaningful markup for search engines. Google and other search engines would be happy to see the correct heading structure. An alternative image is extremely useful as it can tell what particular image actually is about.
- It's the law. In USA, Canada, UK, EU, other unions and countries.
- Because you simply care.
What are the tools that can help us to make web-site accessible?
- Online services:
- Browser extensions:
The list of more popular tools is available on w3c.
How can I make website accessible (the main accessibility part)
There is a lot of documentation you can find and as I mentioned, it might be really overwhelming. However, I want to keep it simple and want you to understand one important piece. Here it's:
There is a technical standard called WCAG. This standard has three levels of conformance: A, AA and AAA. Yes, it might sound complicated, but in fact, it's really simple and you can think about these levels in that way: the higher level you meet, the more accessible your site becomes.
As you might guess each level requires different set of features to implement and the higher the level the more difficult it's to do.
Great! Right now you learned one of the most important theory parts. Let's take that and move to the next section where we would take a look at the requirements for each level.
"A" Level of Conformance
In this part, I'll explain what I feel most important and easy to
implement requirements. That's also a good starting point since we need
to complete A level
before diving into other ones.
Every image should have an alt attribute
That's probably the most known requirement. Here is the problem
though: not everybody knows what kind of information it should contain
and for what purpose it serves. alt
attribute provides an
alternative text to the image if the person couldn't see it or it's not
loaded. From the accessibility point of view it can have two values:
- Null value (That's what W3C says. But, that is not a regular null
value as a separated data type like in Java, PHP or JavaScript. In this
context it actually means empty value or
alt=""
). - Non-null value, i.e. when it actually contains alternative text,
e.g.
alt="Jean Sibelius, the work's composer"
.The question is: when do we need to specify the value and when do we need to leave it empty? The answer: If it's an instructional image you should put an alternative text. If it's a decorative image you can leave attribute empty. In other words, try to remove the image out of the current context. Does the text lose its meaning? If the answer is yes then it's instructional image and you need to provide alt text. Otherwise, it's decorative image and you can leave alt empty.
There is a common mistake regarding instructional image: many editors put image title or description into alt text. That's wrong. You should put the instruction that is provided by the image instead. And again, you can test your alternative text by removing the image and seeing, if your content still has the same sense.
Every link should be meaningfully distinguishable
Example of this can be any blog page that has links like "Read More" or "View More". The problem here is all of these links are identical for the person with disabilities. It's really obvious for a non-disabled person, but in some cases, it's impossible to know the difference what are actual articles links are pointing to for a person with an impairment.
Before going into the solution, let me show you a picture that demonstrates that:
This page has several articles and each one contains the same "Read More" link. Here I wrote some approaches how we would solve it:
1. Apply different title
attribute to each link. For
example
<a title="Read More About Today's events" href="yourblog/post3323">Read More</a>
<a title="Read More About Today's Market" href="yourblog/post1523">Read More</a>
<a title="Read More About Politics" href="yourblog/post9253">Read More</a>
2. Rename each link. For example
<a href="yourblog/post3323">Read More About Today's events</a>
<a href="yourblog/post1523">Read More About Today's Market</a>
<a href="yourblog/post9253">Read More About Politics</a>
3. Use aria-label
attribute. The technique is identical
to title
attribute (where you provide extra description
without affecting actual view), but by using aria-label
instead. title
and aria-label
attributes
wouldn't be shown in the browser except the case when you hover over the
link. W3C - technique
ARIA8
4. Use aria-labelledby
attribute. In this case we need
to have an element the link would refer to. This situation will be
suitable when you already have a unique description for your link and
don't want to be repetitive (and you don't have to). Just assign an id
attribute for the post-headline and point a link to it by using
aria-labelledby
attribute.
<h2 id="post-headline">Events that are happening today</a>
<a href="yourblog/post1523" aria-labelledby="blog-headline">Read More</a>
Screen reader will announce this as "Read more ... Events that are happening today"
Every link should be visually distinguished from the text
This rule implies that all links should have different color from the surrounded text for users who can't distinguish between colors.
Solution: To meet "A" level of conformance text color of each link should differ from the surrounding text by a contrast ratio of at least 3:1. You can use one of the contrast ratio checkers that I mentioned few sections above or anyone you like.
Every page should have right heading structure
The idea behind this requirement is a web page should have a right hierarchy of h1 - h6 tags. I guess, if you're reading this article, you probably know this. However, due to styling reasons, some developers put h3 tags without having h2 on the page which goes against this rule. To meet this requirement there're several points you should avoid:
- Empty heading tags, e.g.
<h2></h2>
. - Multiple H1 tags on a page. As we discussed only one H1 per page.
- Use headings in random order (most of the time this happens because of the styling reasons). Instead, we should organize them in hierarchical/semantical way, where each tag of the "higher rank" precedes to the tag with the "lower rank".
More examples and info about this requirement on W3C
Emphasise text correctly
This is a simple criteria instruct how to use proper HTML5 tags for
text emphasis. In this case <blockquote>
tag might be
a good example of this usage. We can put
<em>, <strong>
tags in the same category.
However, in accordance with this rule, we should definitely avoid
instances of <i>, <b>
tags on the page. These
tags were used in HTML 4.01 to render text in italics/bold. This is not
a case for HTML5 anymore.
In addition to that, a lot of icon fonts (like fontawesome) use <i>
tag. Even though "fontawesome" suggests you to add
aria-hidden="true"
attribute, there're might be other
alternatives. Like this for
example.
Be sure for having unique id across the page
This requirement speaks for itself. Most of the time when you
manually create HTML this doesn't happen. However, many coders forget
about it when they generate HTML elements or components through the
for
loop. An example might be a blog page with a couple
post previews on it. Each of this post would have different visual
content(image, title, subtitle), but in HTML structure it might have the
same id. Just pay attention to that.
Get rid of the presentational attributes if you have ones
This one less likely applicable for modern web. However, if you found
presentational attributes such as
bgcolor, width, border, height, etc
refactor them with
proper CSS styles. In our days you may face them in iframes or old
markup. Just to make sure that we're on the same page, here's piece of
HTML with presentational attributes:
...
<iframe width="560" height="315" src="https://www.youtube.com/embed/Bey4XXJAqS8" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen></iframe>
...
Here width="560
, height="315"
and
frameborder="0"
are presentational attributes.
Refactored version
...
<iframe class="demo-youtube" src="https://www.youtube.com/embed/Bey4XXJAqS8" gesture="media" allow="encrypted-media" allowfullscreen></iframe>
...
h1 {
width: 560px;
height: 315px;
border: none;
}
The full list of presentational attributes can be found on whatwg.
Always set language of the html tag
Pretty easy, but still worth to mention as it is a part of "A" level.
The best way to explain lang
attribute is by example:
<html lang="it"><!--this is lang="it" attribute-->
<head>
<title>Benvenuti</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
...la pagina in italiano...
</body>
</html>
Set descriptive title attribute to an iFrame
The idea is identical to the distinguishable links point, but in this
case, it relates to iframes. Basically, when a person lands on the page
and hears a list of iframes, it's very useful to know the content of
each one. That's where title
attribute can help (yes, the
same attribute like we used in links). Example:
<iframe src="https://www.youtube.com/embed/Bey4XXJAqS8" class="demo-youtube" gesture="media" allow="encrypted-media" title="4k demo video about nature" allowfullscreen></iframe>
Always use labels to describe purpose of the input, textarea or select element
As I found, most code editors or IDEs (in my case it's IDEA based WebStorm/PHPStorm) notifies me when I forget about that rule. It tells that each form control on the page have to be associated with a label. Example:
<label for="email">Email</label>
<input type="email" name="email" id="email" />
or
<input type="email" name="email" id="email" />
<label for="email">Email</label>
or
<label>
Email
<input type="email" name="email" id="email" />
</label>
Either one of those variations is correct. The same logic applies to
textarea
and select
.
There're few exceptions though. Labels shouldn't be used for the following cases:
- Submit and Reset buttons (
input type="submit"
orinput type="reset"
) - Hidden input fields (
input type="hidden"
) - Script buttons (button elements or
<input type="button">
)
These "form controls" already explicitly declared their behavior through their type attribute.
Expose WAI-ARIA attributes (Theory part)
Before going to overwhelm you with another bunch of terms I want to go briefly through another theory part. Let's talk about WAI-AREA a little bit. WAI-AREA (Web Accessibility Initiative – Accessible Rich Internet Applications) or just ARIA is a technical specification published by the W3C that helps increase accessibility of the sites and web-apps. Basically, it's a set of the HTML attributes that can be applied to the elements to provide semantic meaning.
There are three main categories of the attributes defined in the ARIA spec:
Role - attributes belonging to this category provide semantic meaning what element is or does. That’s where we will see “role” attribute in action. You probably already faced with some of the examples like
<header role=“banner”>
,<form role=“search”>
,<footer role=“contentinfo”>
and others. These roles also so-called landmarks (navigational landmarks or landmark roles).Properties - attributes belonging to this category provide extra meaning or semantics. The very basic example, in this case, will be
<input aria-required=“true”>
that shows that input is required.State - attributes belonging to this category define a state of the element. For example
aria-disabled=“true”
, which says that a form input is currently disabled.
You can find all roles, properties and states on W3C.
Another question you may ask: why do we need extra ARIA attributes? After all, we have standard HTML attributes like “required”, “disabled” or HTML5 tag “nav” that says that “nav” is navigation.
The answer is that ARIA attributes are read by assistive technologies. ARIA helps to build “accessible” version of the web page that will be used by screen-readers to reproduce the information. In addition to that, state attributes and properties help handle dynamic page changes (such as disabled-enabled buttons and form fields) which might not be obvious for "helper software" in some cases.
To give you an idea, what actually happens behind the scenes: in
addition to the DOM tree, browsers also expose Accessibility tree
(through the internal API) that is used by screen readers. Actually,
Accessibility tree is the subset of the DOM tree. If you want to
visualize Accessibility tree, there are few ways of doing that. One of
this in Chrome you can open a new tab, navigate to
chrome://accessibility
and you’ll see tree for every tab
opened.
These trees are hidden in the browser by default because it will slow down the browser’s performance. You can click on the “Show accessibility Tree” link to show it.
This is a raw dump of the Accessibility tree. It’s not obvious and difficult to understand, but it can give you an idea how browsers help assistive technologies create accessible information. More about chrome Accessibility tree you can find on Chrome's official website.
When we have some theory, let’s continue to improve accessibility.
Ensure that every HTML5 section does have aria-label or aria-labelledby property to clearly explain its purpose
It's important to know, that each <section>
tag
should have aria-label
or aria-labelledby
attributes from the accessibility point of view. Basically, when we
write <section>...</section>
we provide
meaningful markup and in this case, we should explicitly declare that.
That's what differentiate <section>
from
<div>
. <div>
can be meaningful as
well, but it also can serve for styling purposes whereas
<section>
is always meaningful. Here's an example of
the restaurant web-page that contains dinner menu:
<section aria-label="dinner menu">
<p>Salad</p>
</section>
If we have a declared title, we can point our section to that title by using id:
<section aria-labelledby="dinner-menu">
<h3 id="dinner-menu">Dinner menu</h3>
<p>Salad</p>
</section>
If you want to use meaningful div
for whatever reason
there's another example:
<div role="region" aria-label="dinner menu">
<p>Salad</p>
</div>
<!-- or using aria-labelledby -->
<div role="region" aria-labelledby="dinner-menu">
<h3 id="dinner-menu">Dinner menu</h3>
<p>Salad</p>
</div>
Here I used generic role="region"
landmark and described
it with aria attributes.
Ensure that sections or elements with the same roles are unique
You may face a case when two sections have the same roles. Here's what I mean:
<form role=“search”>
<input placeholder="search globally on the site">
</form>
...
<form role=“search”>
<input placeholder="enter your zip code to find a closest branch">
</form>
In this example, we have two searches, where the first one is a global search (content, articles, info, etc.) and another one is location search. As we mentioned earlier, it might not be obvious for some users. As before, "Aria attributes" come to help:
<form role=“search” aria-label="global search">
<input placeholder="search globally on the site">
</form>
...
<form role=“search” aria-label="location search">
<input placeholder="enter your zip code to find a closest branch">
</form>
Ensure that ARIA Attributes aren't redundant
As we can see from the previous examples "aria attributes" help to describe the purpose of the section and distinguish between identical parts of the page. However, sometimes they can be redundant. Here's an example:
<aside role="complementary">
...
</aside>
<!-- or -->
<nav role="navigation">
...
</nav>
Since we already have semantic aside
and
nav
we don't need to add mentioned role attributes
according to the HTML5 spec.
"AA" Level of Conformance
Provide an ability to skip repeated content
Most web-apps and sites on the internet have blocks that appear on every page. The very common example might be a top navigation. Sometimes these types of blocks can be very long (especially on news portals) and end user should be able to jump straight into article bypassing long sections using keyboard only. I found two real-world examples: American Airlines or Virgin Airlines. When you land on the page and hit "TAB" button a small "skip" popover appears.
"AAA" Level of Conformance
Provide enhanced contrast ratio for the text
We already covered this rule above. However, in order to meet AAA level we need to increase contrast ratio from 3:1 to 7:1 for a normal text and 4.5:1 for a large text.
Conclusion
That's was a basic introduction to accessibility. Of course, there're way more requirements on each level. The main goal of this article is to provide a bridge to web accessibility standards where you can catch on it and continue your own journey. If you are interested to learn more please use links provided in this article. You're also very welcome to share your thoughts in the comments below!
Sources