1. Introduction in Web Accessibility
- understand, navigate and interact with the web;
- contribute to the web.
- auditory;
- cognitive;
- neurological;
- physical;
- speech;
- visual.
- Level A (minimum);
- Level AA (recommended);
- Level AAA (advanced).
2. Images
2.1 Decorative Images
However, if the image has been inserted with the <svg> tag, set the aria-hidden attribute to true (aria-hidden = "true").
-
<!-- Decorative image - <img> -->
-
<img src="image.jpg" alt="" class="image-class">
-
-
<!-- Decorative image - <svg> -->
-
<svg aria-hidden="true"></svg>
2.2 Informational images
- set a role = "img" attribute and an aria-label = "[information conveyed]";
- contain a <title> tag with the same value as the aria-label attribute.
-
<!-- Informational image - <img> -->
-
<img class="informational-image-class" src="image.png" alt="Informational conveyed">
-
-
<!-- Information image - <svg> -->
-
<svg role="img" aria-label="Informational conveyed">
-
<title> Information conveyed </title>
-
</svg>
3.Contrast
4. Tables
- add a <caption> element just after the <title> tag. The text inside the <caption> is the title of the table and allows users to understand what the table contains;
- implement headers in <th> elements;
- add scope="col" on <th> for column headers;
- add scope="row" on <th> for row headers.
-
<table>
-
<caption> List of countries </caption>
-
<thead>
-
<tr>
-
<th scope="col">Countries</th>
-
<th scope="col">Official language</th>
-
<th scope="col">Capital</th>
-
</tr>
-
</thead>
-
<tbody>
-
<tr>
-
<td>Angola</td>
-
<td>Portuguese</td>
-
<td>Luanda</td>
-
</tr>
-
<tr>
-
<td>Bahrain</td>
-
<td>Arabic</td>
-
<td>Manama</td>
-
</tr>
-
<tr>
-
<td>Cameroon</td>
-
<td>Englidh/French</td>
-
<td>Yaoundé</td>
-
</tr>
-
<tr>
-
<td>Danmark</td>
-
<td>Danish</td>
-
<td>Copenhagen</td>
-
</tr>
-
<tr>
-
<td>Egypt</td>
-
<td>Literary arabic</td>
-
<td>Cairo</td>
-
</tr>
-
</tbody>
-
</table>
-
<table>
-
<caption>Increasing number of employees in companies</caption>
-
<thead>
-
<tr>
-
<th id="xcompany" colspan="2">X Company</th>
-
<th id="ycompany" colspan="2">Y Company</th>
-
<th id="zcompany" colspan="2">Z Company</th>
-
</tr>
-
<tr>
-
<th id="1item" headers="xcompany">2017</th>
-
<th id="2item" headers="xcompany">2018</th>
-
<th id="3item" headers="ycompany">2017</th>
-
<th id="4item" headers="ycompany">2018</th>
-
<th id="5item" headers="zcompany">2017</th>
-
<th id="6item" headers="zcompany">2018</th>
-
</tr>
-
</thead>
-
<tbody>
-
<tr>
-
<td headers="xcompany 1item">100</td>
-
<td headers="xcompany 2item">50</td>
-
<td headers="ycompany 3item">80</td>
-
<td headers="ycompany 4item">10</td>
-
<td headers="zcompany 5item">267</td>
-
<td headers="zcompany 6item">22</td>
-
</tr>
-
<tr>
-
<td colspan="2" headers="xcompany">150</td>
-
<td colspan="2" headers="ycompany">90</td>
-
<td colspan="2" headers="zcompany">289</td>
-
</tr>
-
</tbody>
-
</table>
- add a <caption> element just after the <title> tag;
- implement headers in <th> elements;
- add an id (id="xid") for the header;
- ensure that the main header id (id="item") is the same as the multi-level heading attribute (headers="xid");
- ensure that the multi-level heading also has an id;
- add a headers attribute (headers="xid item") on the <td> that contains the values of the headers’ attributes and the id of the <th>.
5.Links
5.1 Picture Links
-
<!-- Image links with an alternative -->
-
<a href="#" class="btn">
-
<img src="https://img.icons8.com/clouds/100/000000/gift.png" alt="Gift">
-
</a>
-
<!-- Image links without an alternative(empty links) -->
-
<a href="#" class="btn">
-
<img src="https://img.icons8.com/clouds/100/000000/gift.png">
-
</a
- on <img> or <area> tags with an href attribute, the alternative is the content of the alt attribute;
- on <object>, <canvas> and <embed> tags, the alternative is contained between the opening and closing tags;
- on the <svg> tag, the alternative is contained in the 'aria-label', 'title' or <desc> tag.
5.2 Composite links: Image and text
-
<!-- Composite links (decorative image and text) -->
-
<a href="#" class="btn">
-
<img src="https://img.icons8.com/clouds/100/000000/gift.png" alt="">
-
Gift
-
</a>
-
<!-- Composite links (image with irrelevant alternative -->
-
<a href="#" class="btn">
-
<img src="https://img.icons8.com/clouds/100/000000/gift.png" alt="gift.png">
-
Gift
-
</a>
5.3 Empty links
5.4 Title of links
- the same title as the link title;
- the title voids.
6 Multilingual content
-
<p lang="en">Go to the next lesson</p>
-
<p lang="ro">Mergi la urmatoarea lectie</p>
-
<p lang="fr">Aller à la suivant leçon</p>
Code 6: Lang attribute
<p lang="ar" dir="rtl">انتقل إلى الدرس التالي</p>
7. Structuring information:
7.1 Headings
- the page must have at least one <h1> title;
- the title hierarchy must be consistent (For example, after an <h3>, you should have an <h4> or another <h3>, but especially not an <h5>);
- all necessary titles must be present.
-
<div>
-
<h1>Main heading</h1>
-
<p>Structure of a page is very important</p>
-
<h2>About</h2>
-
<p>This is a demo</p>
-
<h3>Example heading level 3</h3>
-
<p>Dummy text</p>
-
<h3>Subtitles</h3>
-
<p>Another dummy text</p>
-
</div>
Bad practice
-
<div>
-
<div role="heading" aria-level="1">Main heading</div>
-
<p>Structure of a page is very important</p>
-
<p>This is a demo</p>
-
<h3>Example heading level 3</h3>
-
<p>Dummy text</p>
-
<div role="heading" aria-level="2">About</div>
-
<h3>Subtitles</h3>
-
<p>Another dummy text</p>
-
</div>
7.2 Document structure (tags & roles)
- the main header;
- the main content;
- the main and any secondary navigation;
- the footer;
- the search engine;
- the main header - <header> with role="banner"
- the main content - <main> with role="main
- the navigation - <nav> with role="navigation"
- the footer - <footer> with role="contentinfo"
- the search engine - role="search"
- several header tags can be found but their role="banner" attributes must be unique in the page;
- the main tag and role=" main" attribute are unique in the page;
- several footer tags can be found but their role="contentinfo" attributes must be unique in the page;
- the role="search" attribute is unique in the page;
- we can find several nav tags and also several role="navigation" attributes.
-
<header role="banner" class="c-header">
-
<!-- Header content goes here ... -->
-
</header>
-
<nav role="navigation" class="c-main-navigation">
-
<!-- Navigation content goes here... -->
-
</nav>
-
<div role="search">
-
<!-- Search content goes here... -->
-
</div>
-
<main role="main" class="c-main-content">
-
<!-- Main content goes here... -->
-
</main>
-
<footer role="contentinfo">
-
<!-- Footer content goes here... -->
-
</footer>
-
<div class="c-header">
-
<!-- Header content goes here ... -->
-
</div>
-
<div class="c-navigation">
-
<!-- Navigation content goes here... -->
-
</div>
-
<div class="c-content">
-
<!-- Main content goes here... -->
-
</div>
-
<div class="c-footer">
-
<!-- Footer content goes here... -->
-
</div>
7.3 Citations
-
<blockquote> "I was within and without, simultaneously enchanted and repelled by the inexhaustible variety of life"
-
<cite>Fitzgerald F. Scott, The Great Gatsby</cite>
-
</blockquote>
8 Presentation of information
8.1 Using CSS exclusively
-
<!-- "align" attribute in this context is prohibited -->
-
<div align="right">
-
<!-- "width" and "height" are ok on the <img> tag -->
-
<img src="img.png" width="100%" height="100%">
-
</div>
8.2 Making content visible without stylesheets
-
<div class="c-v__thumbnail" style="background-image:url('')">
-
<div class="c-locked-icon"></div>
-
<span class="sr-only">Blocked Exercise</span>
-
</div>
-
-
<div class="c-v__thumbnail" style="background-image:url('')">
-
<div class="c-locked-icon"></div>
-
</div>
8.3 Enlarging text size (fixed units)
- set text size in relative units;
- avoid setting box sizes in fixed units;
- use certain CSS properties with caution.
-
<!-- Recommended -->
-
.class {
-
min-height:50px;
-
}
Bad practice
-
<!-- Not Recommended -->
-
.class {
-
height:50px;
-
}
9. Forms
- have relevant labels;
- use a consistent method to link the fields to their respective labels;
- keep a simple and clear structure.
-
<label for="name">Name</label>
-
<input type="type" id="name"/>
This implementation is really helpful for a checkbox because by clicking on the label, the checkbox get checked.
-
<label for="yes">Yes</label>
-
<input type="radio" id="yes" value="item1" name="items"/>
-
<label for="no">No</label>
-
<input type="radio" id="no" value="item2" name="items"/>
-
<label>Yes
-
<input type="radio" value="item1" name="items"/>
-
</label>
-
<label>No
-
<input type="radio" value="item2" name="items"/>
-
</label>
- a label (e.g. <label>E-mail (required)</label>);
- an asterisk (*).
- use the <fieldset> tag;
- add a <legend>Title</legend> just after the <fieldset> tag;
- properly bind fields and labels;
- make sure that check/uncheck function works with the arrows keyboard.
10 Navigation
10.1 Navigation systems
- not all users navigate in the same way;
- some navigation systems may be too complex to use, especially for people using assistive technologies.
- a main navigation menu;
- a site map;
- a search engine.
10.2 Fast access links
- a link that provides access to the main content area;
- a link that provides access to each group of important links (e.g. navigation menu).
-
<!-- Hidden fast access links visible to focus capture -->
-
a {
-
position: absolute;
-
top: -10000px;
-
&:focus {
-
top: 0;
-
}
-
}
-
-
<!-- Fast access links always visible -->
-
a {
-
position: static;
-
top: -10000px;
-
}
Bad Practice
-
<!-- Hidden and inaccessible fast access links -->
-
a {
-
display: none;
-
&:focus {
-
display: block;
-
}
-
}
Code 15: Fast access links
- display: none;
- visibility: hidden;
- width:0; and height: 0;
- font-size: 0;
- hidden HTML5 attribute;
- aria-hidden="true" ARIA property.
10.3 Consistent tab order
- 0, which means that the element can receive focus and can be accessed with the tab key in the natural order of the source code. You can even make the elements that are not natively interactive (<div>, <p>, <span>, etc.) focusable.
- -1, which means that the element can receive focus, but can't be accessed with the tab key.
- It’s better to avoid any value greater than 0.
- Use -1 to move the focus to elements that have their focus set using scripts.
- Use 0 only for elements that are not natively interactive.
-
<a href="#">Link</a>
-
<button>Press me</button>
-
<div tabindex="0"> I receive focus</div>
-
<span tabindex="0">I also receive focus</span>
-
<div tabindex="-1">I receive focus from J</div>
-
<a href="#">Another link</a>
Bad Practice
-
<a href="#" tabindex="0">Link</a>
-
<button tabindex="1">Button</button>
-
<ul>
-
<li><a href="#" tabindex="2">Link inside list</a></li>
-
<li><a href="#" tabindex="3">Link inside list</a></li>
-
<li><a href="#" tabindex="4">Link inside list</a></li>
-
</ul>
-
<div tabindex="0"></div>
Code 16: Tab order
- The element that shows and hides the content must have the button role.
- The element with the button role must have the aria-expanded attribute set to true when the content is visible, otherwise, it should be set to false.
- When the disclosure control has focus, the enter and space keys toggle the visibility of the disclosure content.
-
<!-- Hidden state -->
-
<button aria-expanded="false" aria-controls="example-good">Press me</button>
-
<div id="example-good" style="display: none;"></div>
-
<!-- Status displayed -->
-
<button aria-expanded="true" aria-controls="example-good">Press me</button>
-
<div id="zone" style="display: block;"></div>
Bad Practice
-
<!-- Hidden state -->
-
<button role="button" class="toggle-me" aria-label="Toggle content"></button>
-
<div id="bad-example" style="display: none;"></div>
-
<!-- Status displayed -->
-
<button role="button" class="toggle-me" aria-label="Toggle content"></button>
-
<div id="bad-example" style="display: block;"></div>
12. Carousels
- navigation items (previous/next arrows) must be buttons (HTML button tags or ARIA buttons);
- a method of consistent navigation between the navigation area and the controlled content area;
- if the carousel is automatically scrolling, a method to pause and restart must be provided ("play" / "pause" buttons);
- Basic
- Tabbed
- Grouped
- a carousel container element, which must include all the components of the carousel;
- The carousel container has the aria-roledescription property set to the carousel;
- The controllers are native buttons;
- If the carousel has a visible label, its accessible label is provided by the aria-labelledby property;
- Each slide container has its role group with the aria-roledescription property set to slide;
- Each slide has an accessible name.
-
<section class="carousel"
-
aria-roledescription="carousel"
-
aria-label="My carousel example">
-
<div class="carousel-inner">
-
<div class="controls">
-
<button
-
class="previous"
-
aria-controls="exampleCarousel-items"
-
aria-label="Previous slide">Prev</button>
-
<button
-
class="next"
-
aria-controls="exampleCarousel-items"
-
aria-label="Next slide">Next</button>
-
</div>
-
<div class="carousel-items"
-
id="exampleCarousel-items"
-
aria-live="off">
-
<div class="exampleCarousel-items"
-
role="group"
-
aria-roledescription="slode"
-
aria-label="1 of 3">
-
<img src="" alt="Carousel image">
-
</div>
-
<!-- Next slide items -->
-
</div>
-
</div>
-
</section>
-
<section class="carousel"
-
aria-label="Image example">
-
<div class="carousel-inner">
-
<div class="controls">
-
<span class="next-slide"
-
aria-label="Next slide">Next</span>
-
<span class="previous-slide"
-
aria-label="Previous slide">Prev</span>
-
</div>
-
<div class="carousel-items">
-
<div class="carousel-items"
-
aria-label="Carousel item">
-
<img src="" alt="Carousel image">
-
</div>
-
<!-- Next carousel slides -->
-
</div>
-
</div>
-
</section>
Code 18: Carousel
13. Modal windows
- Add role = "dialog", aria-modal = "true", and tabindex = "- 1" on the container of the modal;
- Add a representative name to the modal:
- aria-label="[Window Title] property;
- or aria-labelledby = "title-id" linked to a passage of text identified as the title.
To understand better the way in which an accessible modal works, you should know the following:
- when opening the modal window, the focus goes on its first focusable element (it could be an input, a link or some other element, or even the modal window itself);
- the focus moves only between the tabular elements of the modal window, it never traverses the contents in the background;
- the Esc key closes the modal window;
- when closing the modal, the focus is returned to the element in the content that opened the modal.