💡 Introduction to Web Accessibility and WCAG 2.1
What is Web Accessibility?
Web accessibility refers to the inclusive practice of ensuring that websites, tools, and technologies are designed and developed so that people with disabilities can use them. More specifically, it means that people can:
Perceive, understand, navigate, and interact with the web.
Contribute to the web.
Web accessibility encompasses all disabilities that affect access to the web, including:
Auditory
Cognitive
Neurological
Physical
Speech
Visual
Perceivable
Guideline 1.1
Basic principles to meet this criterion:
Images, image maps, and map points should have appropriate alternative text.
Decorative images or content already included in the text should have an empty “alt” attribute.
Alternative text for more complex images should be provided as a description or a link to a separate page.
Form buttons should be accurately described (using the “name” attribute).
<input/> fields should have a <label> tag with the field name.
iframe should have an appropriate title.
Non-text content should have a brief description of what it represents. To decide what text should be added, consider the following questions:
Why is the content here?
What information does it present?
What is the purpose of this type of content?
If non-text content could not be used, how could the content be conveyed in words?
If non-text content contains words essential for understanding the content, the alternative text should include those words. The text should be short and concise. If a more detailed description is needed, the illustration can be a link to a separate page with the description, or the description can be placed next to the illustration.
For <img/> tags, add an “alt” attribute with a brief description of what is in the image:
<imgsrc="cat.jpg"alt="Cute cat with people" />
When using SVG, add alternative text describing what the SVG represents. This can be achieved by adding a <title></title> tag as the first child of the <svg></svg> tag:
<svgversion="1"id="cat"viewBox="0 0 720 800"aria-labelledby="catTitle catDesc"role="img">
<titleid="catTitle">Cat in home</title>
<descid="catDesc">Cute cat in home with people</desc>
<path>...</path>
</svg>
Adding <desc> is optional and should be used if it helps in understanding the content presented by the SVG. The “role=img” attribute is added to improve HTML document parsing by screen readers, identifying the element as an image.
Guideline 1.2
Accessibility of pre-recorded audio and video files:
Provide transcripts or audio descriptions for all non-live recordings.
Example of adding an audio description:
<ahref="video/examination.mp4"><imgsrc="images/examination.jpg"alt="Examination technique - animation" /></a>
<ahref="examination_audio.mp3">Audio description for the animation "Examination technique"</a>
Exclusions are videos used solely for decoration.
Subtitles in video materials should convey audio information affecting context understanding, beyond dialogues. For higher accessibility (AAA), video material should include a sign language translation recording.
Live materials should have subtitles.
Guideline 1.3
The HTML document should be built with semantic elements, and each element should be used for its intended purpose. Tables should be used for tabular data, and data cells should be associated with their headers. Table captions, if present, should be associated with data tables.
The document should maintain logical content continuity and allow for logical and intuitive navigation. Instructions should not rely solely on shape, size, or visual location (e.g., “Click the square icon to continue” or “Instructions are in the right column”). They should not rely solely on sound (e.g., a sound indicating the end of time as the only indicator of time passing).
Content orientation should not affect functionality. Helpful techniques include:
Using CSS orientation with “landscape/portrait” values.
Using show/hide to hide elements in the appropriate orientation.
<input/> fields should have appropriately filled “autocomplete” attributes:
Document regions should have appropriate labels indicating the part of the document they represent if the document’s semantics do not allow it. ARIA is used, where applicable, to enhance HTML semantics for better identification of interface component purposes.
Guideline 1.4
Distinguishable: Make it easier for users to see and hear content, including separating foreground from background.
Color should not be the only way to distinguish and communicate content changes. Such communications should also be conveyed in text form.
Choose a font color that ensures full visibility against the background.
Text and the entire page should be readable and should not lose functionality. In version 2.0, it was recommended to maintain page readability at 200% zoom. In version 2.1, this is now 400%.
Limit the number of images presenting only text content, and present such content in text form whenever possible.
Comfortable content viewing also depends on appropriate line size and the number of characters per line.
Text should not exceed 80 characters per line.
Text should not be justified.
Line spacing should be 0.5 * font size.
Paragraph spacing should be 1.5 * line spacing.
Text should not require horizontal scrolling even when zoomed (max 400% WCAG 2.1).
Guideline 4.1.1
Document parsing should be error-free. The goal of this technique is to avoid ambiguity on web pages, often resulting from code that does not validate against formal specifications. The mechanism of each technology is used to determine the technology and version of the technology, and the web page is checked against the formal specification of that technology. The basis for meeting this guideline is using correct HTML tags and ensuring they are properly closed.
Guideline 4.1.2
Tags are used in a way that facilitates access. This includes adhering to HTML/XHTML specifications and appropriately using forms, form labels, frame titles, etc. ARIA is appropriately applied to enhance accessibility when HTML is insufficient.
Guideline 4.1.3 (WCAG 2.1)
If a valid status message is displayed and focus is not set on that message, the message should be announced to screen reader users, usually via an ARIA alert or live region.
Principle of Functionality
Keyboard - Ability to Navigate the Site Using Only the Keyboard
Use [tab], [space], [enter], [esc], [home], [end], [pageUp], [pageDown], [arrowUp], [arrowDown], [arrowRight], [arrowLeft] to navigate the site. Ensure that each element can be entered and exited.
Ensure the tab order of the site is logical and consistent with the visual order of elements on the page.
<nav>
<ul>
<li>
<ahref="index.html"title="Go to the home page">Home</a>
</li>
<li>
<ahref="index.html"title="Go to the offer page">Offer</a>
</li>
<li>
<ahref="index.html"title="Go to the contact page">Contact</a>
</li>
</ul>
</nav>
If the focus is on the “Home” element, pressing [tab] will change the focus to “Offer”. Pressing [shift + tab] will return to “Home”.
tabindex is an integer indicating whether an element can be focused and should be considered in sequential keyboard navigation, and if so, in what order. It can take several values:
A negative value means the element should be focusable but not reachable through sequential keyboard navigation.
0 means the element should be focusable and reachable through sequential keyboard navigation, but its relative order is defined by the platform’s convention.
A positive value means the element should be focusable and reachable through sequential keyboard navigation; its relative order is defined by the tabindex attribute value: the sequence follows the increasing tabindex value. If some elements have the same tabindex, their relative order depends on their relative position in the document.
An element with a value of 0, an invalid value, or no tabindex value should be placed below those elements in sequential keyboard navigation that have a positive tabindex.
If we set the tabindex attribute on a <div>, its descendant content will not be scrollable using arrow keys unless we also set tabindex on the content.
The following example illustrates the use of tabindex order to maintain a logical field-filling sequence for the user. This means that when filling the [first name] field, the user expects the next field to be [last name].
<fieldset>
<legend>Sample Form</legend>
<divclass="wrapper-blocks">
<divclass="wrapper-block-fields">
<labelfor="name"class="label">First Name (tabindex1)</label>
<inputtabindex="1"id="name"class="input"type="text" />
<labelfor="street"class="label">Street (tabindex3)</label>
<inputtabindex="3"id="street"class="input"type="text" />
</div>
</div>
<divclass="wrapper-block-fields">
<labelfor="surname"class="label">Last Name (tabindex2)</label>
<inputtabindex="2"id="surname"class="input"type="text" />
<labelfor="houseNr"class="label">House Number (tabindex4)</label>
<inputtabindex="4"id="houseNr"class="input"type="text" />
</div>
</fieldset>
Remember that the user must be able to enter navigation only when they want to. By default, most navigation is simply hidden, so tabbing through the page may result in several “empty” tabs where nothing happens. Google has addressed this issue using the ‘inert.js’ script.
Google’s approach: YouTube
Script: GitHub
When navigating the site using the keyboard, the focus is always visible on the selected element. The focus must be visible on clickable elements, links, inputs, forms, buttons. Global focus for all clickable elements:
* {
outline: 2pxdashedorange;
}
Keyboard users must be able to easily use and close modal dialog boxes, lightboxes, and other pop-up windows. The focus must be moved to the displayed element.
When the modal is activated, the focus should be on the first clickable element inside the modal.
As long as the dialog/modal is open, the focus is limited to elements within that window.
The user must have access to all control elements to close the window using:
The [ESC] key.
The close button in the modal [close/icon].
Remember that if an HTML element has a tabindex attribute with a negative value, e.g., tabindex="-1", the element will not be accessible from the keyboard.
Navigability
Bypass block - allow skipping navigation directly to the main content of the application. Example: CodePen
Appropriate titling of pages/subpages. Remember that proper page titling is good for screen readers and also for SEO. Example title for the home page:
<head>
<title>Media Company Website</title>
</head>
Example title for a subpage:
<head>
<title>Media Company Website - Contact</title>
</head>
Link text should be clear, understandable, and descriptive. Example:
<ahref="wikipedia.org">
Go to the Wikipedia page
</a>
Headings and labels should be appropriately described. That is:
Only one main heading <h1></h1> for the website.
Maintain heading hierarchy, i.e., headings should be assigned starting from <h1> to <h6>. (In practice, <h5> and <h6> are rarely used). Headings <h2>-<h6> can be used multiple times, but remember to write headings in order. Also, remember to provide meaningful content for headings. W3C Example
Example:
<h1>ROK Marketing Agency</h1>
<h2>Solutions</h2>
<h3>Digital Marketing</h3>
<!-- further code... --> <h3>Influence Marketing</h3>
<!-- further code... --> <h2>Security Solutions</h2>
<h3>CDN</h3>
Providing descriptive labels is very important. Remember that the <label> field must be understandable to the user.
<label>Last Name</label>
Describing in the label field that the field is required (ARIA techniques will be described later):
<label>Last Name (required field)</label>
<!-- or --><label>Last Name*</label>
*- required fields
(Lvl AAA) Providing appropriate information about the user’s location, e.g.:
For user interface components with labels containing text or images of text, the name includes the visually presented text. The goal of this technique is to ensure reliable operation of web content by users entering screen readers. Examples:
The link contains visible text and hidden link text. Both together create an accessible link name. The visible text is the most important. The idea is to make the link more descriptive for assistive technology users.
<p>Go to <ahref="code-of-conduct.html">Code of conduct <spanclass="hidden_accessibly"> of ACME Corporation</span></a><p>
A general link is combined with the paragraph heading to provide context. This is a variation of the first example, this time using aria-labelledby. The advantage of this implementation is that it uses existing visible text on the page, making it more likely to be correctly translated during any localization transformations.
<h4id="poor">Insufficient Link Names Invade Community</h4>
<p>Citizens are reeling from the growing invasion of useless "read more" links appearing in their online resources.
<ahref="poor.html"aria-labelledby="generic poor">
<spanid="generic">More...</span>
</a>
Where two strings cannot be grammatically or smoothly combined using aria-labelledby, aria-label can be used to create a new name containing the visible label.
...end of news story. <ahref="poor.html"aria-label="Read more about Insufficient link names">Read more</a>
The visible text inside the button element corresponds to the beginning of the accessible name, which also includes hidden text. The purpose of the hidden text is to make the button more descriptive for assistive technology users.
The visuallyhidden CSS class can be used to present invisible text (which should be visible to screen readers). Useful, for example, for buttons with icons that do not have text. visuallyhidden in CSS:
Using conventional HTML, the text between the anchor element tags provides both the visible link text and the accessible name “Code of conduct”:
<p> Go to our <ahref="url-to-page-about-code.html"> Code of conduct </a> </p>
The text between the label tags also serves as the accessible name for the checkbox “Notify me of delays” using the for attribute, which refers to the input’s ID.
<inputtype="checkbox"id="notification"name="notify"value="delays">
<labelfor="notification">Notify me of delays</label>
The text inside the button element becomes both the visible label and the accessible name:
<button>Send</button>
Radio buttons usually appear in a group, where each button is labeled, and the group of buttons is preceded by information explaining or categorizing the group.
<fieldset>
<legend>Call me when balance exceeds $10,000?</legend><br />
<inputtype="radio"id="yes"name="callme"value="yes">
<labelfor="yes">Yes</label>
<inputtype="radio"id="no"name="callme"value="no">
<labelfor="no">No</label>
</fieldset>
A good practice is to place the label field above the input field. This is useful when, for example, we need to zoom in (200%), then on the zoom, we have the entire input along with the text.
A less common discrepancy between labels and inputs can occur when a group of radio buttons is configured to obtain a selection across a range. Labels may only be placed at each end of the range or interspersed at various points within the range. Online example: W3C Example
Principle of Understandability
Readability
Language of the Page
The goal of this technique is to identify the default language of the document by providing the lang attribute on the HTML element. Specifying the document’s language is important for several reasons:
It allows Braille translation software to replace control codes with accented characters and insert control codes necessary to prevent incorrect formation of Grade 2 Braille contractions.
Multilingual speech synthesizers can orient themselves and adjust to the pronunciation and syntax characteristic of the page’s language, pronouncing the text with the appropriate accent and pronunciation.
Language designation can benefit future technology development, such as users who cannot translate between languages being able to use machines to translate unknown languages.
Language designation can also help user agents create definitions using a dictionary.
The human language of each passage or phrase in the content can be programmatically determined, except for proper names, technical terms, words in an undefined language, and words or phrases that have become part of the vernacular of the surrounding text.
<blockquotelang="pl">
<p>Today the beautiful sun is shining</p>
</blockquote>
Predictable
When any user interface component receives focus, it does not initiate a change of context. The goal of this technique is to provide a method of activation that is predictable by the user. Users with cognitive disabilities and those using screen readers or screen magnifiers may be confused by an unexpected event, such as an automatic form submission or activation of a feature that causes a change of context. With this technique, all context changes would be triggered only by a specific user action. Moreover, such an action typically causes context changes, such as clicking a link or pressing the submit button. Actions that simply move focus to an element would not cause a context change. Example:
A page pops up in a new window only when the user clicks a button (or uses the spacebar) on the button instead of using onfocus to display the new window.
The submit button is used to move to the next data entry screen instead of automatically displaying the next screen when the user clicks the “done” button.
Changing the setting of any user interface component does not automatically cause a change of context unless the user has been informed of the behavior before using the component. Example:
The submit button is used for each form that causes a change of context.
Navigation mechanisms that are repeated on multiple web pages within a set of web pages occur in the same relative order each time they are repeated unless the user initiates a change. Example:
The navigation menu always appears in the same order on different subpages.
Components that have the same functionality within a set of web pages are consistently identified. Examples:
A website has a form field at the top of the page labeled “Search.” At the bottom of the page, there is another form field that provides the same function. It is also labeled “Search.”
An image of a question mark is used to direct users to sections of the page that contain additional information. Each time the question mark image appears, it has the same alternative text “more information.”
A link to the Contact page of a website contains the text “Contact.” At the bottom of the page, there is a link that also leads to the Contact page. It also has the link text “Contact.”
Input Assistance
If an error is detected, the user is informed of it textually. The goal of this technique is to notify the user when a required field has not been filled out. When users do not provide input for any required fields in a form, information is provided in text to allow users to determine which fields were omitted. One approach is to use client-side validation and provide a dialog box warning identifying the required fields that were omitted. Another approach, using server-side validation, is to redisplay the form (including any previously entered data) with a textual description at the location of the omitted required field or a textual description identifying the omitted required fields. Best practice is to include a message or alert, as some users may not be aware of the error and may assume the form is not working correctly. Best practice is also to place the error notification in the page title (title element), as a screen reader user is likely to assume the page was submitted correctly and continue navigating to another page as soon as the new page is returned instead of reading the main content area of the page again. More techniques provided by W3C. Examples:
Using aria-invalid, aria-required, aria-describedby in required fields:
Using [aria-alertdialog] to identify errors. The goal of this technique is to alert people to the occurrence of an input error. Using role="alertdialog" creates a notification. This notification should be modal with the following features:
The aria-label or aria-labelledby attribute gives the alert dialog an accessible name.
aria-describedby provides a reference to the warning text.
The alert dialog contains at least one control that can be set, and focus should move to this control when the alert dialog opens.
The tab order is limited to the alert dialog when it is open.
When the dialog is closed, focus moves back to the position it had before the dialog opened, if possible.
Note that the alert dialog should not be present in a way that makes it accessible to AT until it is needed. One way to do this is to not include it in the static HTML code and instead insert it into the DOM using a script when the error condition is triggered. The insertion would correspond to the following HTML example. (online example)
<divrole="alertdialog"aria-labelledby="alertHeading"aria-describedby="alertText">
<h1id="alertHeading">Error</h1>
<divid="alertText">Employee's Birth Date is after their hire date. Please verify the birth date and hire date.</div>
<button>Save and Continue</button>
<button>Return to page and correct error</button>
</div>
Using the aria-describedby property to provide a descriptive label for user interface controls (more aria-describedby examples) (online code example):
<buttonaria-label="Close"aria-describedby="descriptionClose"@click="closeDialog()">X</button>
<divid="descriptionClose">Closing this window will discard any information entered and return you back to the main page</div>
The aria-labelledby property can be used to label all visual objects. For inputs, the aria-labelledby property can be used to label native inputs. One particular use of aria-labelledby is for text input in situations where a significant label should consist of more than one label string.
The goal of this technique is to help the user avoid input errors by informing them of the format constraints for the data they need to enter. This can be done by describing the format features or providing a sample format for the data. For example, informing in the label about the format to be entered:
<label>Enter date (dd-mm-yyyy)</label>
The goal of this technique is to help the user avoid input errors by informing them in advance of the format constraints for the data they need to enter. Instructions for such constraints are placed at the top of the forms. This technique works best for forms with a small number of fields or those where many form fields require data in the same format. In such cases, it is more efficient to describe the format once in the instructions at the top of the form than to repeat the same information for each field that has the same format requirements.
Indicating Required Controls Using a Label or Legend
Using text to indicate required status:
<labelfor="firstname">First name (required):</label>
<inputtype="text"name="firstname"id="firstname" />
Using an asterisk to indicate required status:
<labelfor="firstname">First name <abbrclass="req"title="required">*</abbr>:</label>
<inputtype="text"name="firstname"id="firstname" />
Indicating required status for groups of radio buttons or checkboxes. Radio buttons and checkboxes are treated differently from other interactive controls because individual radio buttons and checkboxes are not required, but a response is required for the group. The methods applied in examples i-ii apply to radio buttons and checkboxes, but the indication of required status should be placed in the legend element instead of the label element.
<fieldset>
<legend>I am interested in the following (Required):</legend>
<inputtype="checkbox"id="photo"name="interests"value="ph">
<labelfor="photo">Photography</label><br>
<inputtype="checkbox"id="watercol"name="interests"checked="checked"value="wa">
<labelfor="watercol">Watercolor</label><br>
<inputtype="checkbox"id="acrylic"name="interests"checked="checked"value="ac">
<labelfor="acrylic">Acrylic</label>
</fieldset>
Using label elements to associate text labels with form controls. The goal of this technique is to use the label element to explicitly associate a form control with a label. The label is attached to a specific form control using the for attribute. The value of the for attribute must be the same as the value of the id attribute of the form control.
Using automatic labeling to associate text labels with form controls.
Error Prevention
Providing the user with the ability to review and correct responses before submission.
Requesting confirmation to continue with the selected action.
Providing the ability to recover deleted information (online example): A web application allows users to configure folders and store data in them. Each folder and data item is accompanied by a checkbox indicating an action and two buttons, one to move and one to delete. If the user accidentally selects the delete button, large amounts of data could be lost. The application immediately displays the data as deleted but plans to actually delete it within one week. During the week, the user can go to the “deleted items” folder and request the restoration of any folder or data item pending actual deletion.
Examples
Semantic HTML - a somewhat ‘aged’ material from Comandeer, but still relevant - a description of the semantic structure of a page. (Comandeer - Tomasz Jakut - probably the best Polish specialist in WebAccessibility).
Webkrytyk - a site run by Comandeer. It contains a lot of information on how not to create websites.
W3C Examples - a list of the best techniques from W3C for applying the standard.
ARIA - cheat sheet - a list and description of ARIA tags.
Most are unfortunately paid. Screen readers are also dedicated to different systems: Android, iOS, Windows, Ubuntu, and different browsers (Chrome, Firefox, Safari).
NVDA Screen Reader
ChromeVox (for Chrome, enabled in browser options)