[Narrator:] In this chapter you will learn how to code accessible web pages. Although you can follow this course without any technical knowledge, it is beneficial if you know how to write HTML code and Cascading Style Sheets. To reproduce our examples, it is sufficient to use a basic plain text editor. What-you-see-is-what-you-get editors that create the HTML code for you are less advantageous, as you only have limited control over the code creation process.
This chapter does not follow the structure of the web standards. We will follow a more practical approach from basic to more complicated solutions. For details, always use the web standards as a reference.
In this chapter we will discuss how semantic elements can describe the meaning of content. We will see how we can hide content from or show content only to screen readers. We will introduce different ways to add alternative texts to visual content. With an example, we will show how to create useful link texts. We will demonstrate how code can influence navigation via the keyboard. We will give special attention to how to create accessible forms. We will discuss the correct coding of web pages with content using multiple languages. Finally, we will have a short look at the Web Accessibility Initiative Standard for creating Accessible Rich Internet Applications.
HTML 5 semantic elements
Semantics describe the meanings of words and phrases in a language. An HTML element with semantics describes its role as part of the document. Examples of non-semantic elements are the div and the span elements. These elements group content together without any meaning. Their visual appearance can only change with an additional style sheet rule.
Examples of HTML elements with semantics are the heading elements h1 to h6, the li list, or the table element. These elements result in specific types of rendering without any additional style sheet rules. Their pure presence describes a structure in a document.
Let's compare a heading with and without a semantic element. Both lines may be visually rendered in the same way. The first line creates a line formatted with a style sheet. A screen reader has no possibility to detect that this line describes a heading. The second line describes a heading by its semantic element. This can be detected by a screen reader. So, please, always use the appropriate semantic elements to describe the structure of your document. Never use a non-semantic element to replace it.
The HTML 5 standard added additional semantic elements to the standard. Here are some examples.
HTML 5 semantic element <article>: The article element specifies independent, self-contained content. It can be used to group content. A document can have multiple articles; for example, a blog that shows the text of each article one after another.
HTML 5 semantic element <header>: Semantic elements can be nested; for example, a header inside an article. The header element specifies a header for a document or section. It should contain introductory content.
HTML 5 semantic element <nav>: The nav element defines a set of navigation links. It should only be used for major blocks of navigation links.
HTML 5 semantic element <aside>: The aside element defines content aside from the content it is placed in, like a sidebar. Its content should be related to the surrounding content.
HTML 5 – more semantic elements: The HTML 5 standard introduced more semantic elements, which you can see here on the screen. We will not provide an example for each one. Some of them will be discussed in later sections of this chapter. For now, we list them here for completeness.
Hide content from or show content only to screen
Content only visible to screen readers: We can create content that will be rendered by screen readers only. Conversely, we can hide content from screen readers, so that it is only presented to sighted users. Screen readers do not care where an element is positioned on the screen. They analyse the HTML code and read one element after another in the sequence in which they appear in the HTML code. This mechanism can be used to create content that will be rendered by screen readers only. We define a style, which we name screen reader. Of course, you can choose any other name too. Each element using this style will be positioned outside of the visible window area. As a screen reader does not care about the position on the screen, it will read its content, whereas a sighted user will not see it.
Content hidden from screen readers only: If you want to hide content from screen readers, then use the aria-hidden attribute. We often see developers trying to hide content from screen readers in this way. Please note that the display and visibility style properties hide content from screen readers and from sighted users. So do not use them to hide content from screen reader users or sighted users.
Adding alternative text to non-text content is the first principle of accessibility. Although it sounds simple, it is not. This course offers a complete chapter on writing alternative text. If you do not know what alternative text is or how to write this, we highly recommend that you study this chapter.
In this chapter, we will learn how to embed alternative text into web pages.
Here we see a very simple example of an alternative text. The alt attribute of an image allows us to enter alternative text that can be spoken by a screen reader. If an image has no alternative text, then the filename will be spoken, which in this case would not be very helpful.
The title attribute presents advisory information. Most browsers render the content of the title attribute as a pop-up, which appears when the mouse pointer rests over the element. Please note that while a title attribute can be helpful, it is difficult for users of touch-oriented devices to use. The content of the title attribute is not used by screen readers if an alternative text exists. This leads us to the question: what information is used by a screen reader when reaching for an alternative text? Text alternative computation: Based on the intended behaviour, the precedence for calculating a text alternative should be: aria-labelledby, aria-label, alt, title. When two or more of the above are used, whichever is highest in the list will be used. We have already seen the alt and the title attributes, so let's have a look at the other two.
The aria-label attribute: The aria-label attribute is used to define a text that labels the current element. We have seen the practical influence of the aria-label attribute in the previous chapter, when we compared an inaccessible web page with an accessible one. The web page had two different navigation blocks, each with its own type of menu. To make them distinguishable for a user, we add a label to the navigation block. The label will be spoken once the screen reader cursor reaches the element. Why do we need an aria-label attribute when we could have an alt attribute? The answer is simple. The HTML standard allows the use of an alt attribute only in the context of an img, area, or input element. For anything else you should use the aria-label attribute.
The aria-labelledby attribute: The aria-labelledby attribute establishes relationships between objects and their labels. Its value should be one or more element IDs, which refer to elements that have the text needed for labelling. This attribute is often used in combination with accessible forms when form input elements need to be associated with their labels. We will discuss accessible forms later in this chapter.
Captions: Often descriptions of images need to be displayed for sighted users too. In this case we would like to have a caption positioned close to the original image. The HTML 5 semantic elements figure and figcaption can be used to enclose both the image and its long description. The long description is wrapped in the figcaption element. Please note that you can use an alt attribute and a figcaption element at the same time. The figcaption element may contain complex data. Here is an example with a heading, paragraph and table.
Alternative text for symbol fonts: Sometimes graphics on web pages are not created by image files. They are created by symbol fonts, defined in style sheets. As they are graphics, they need alternative texts, so that they can be recognised by users with visual disabilities. There are multiple ways to achieve this goal. Our first example is a menu presenting a social media menu. Each menu item is created with a class of its own, which refers to a style sheet entry defining the font graphic. As this is just a hyperlink created with an a tag we cannot use an alt attribute here. Therefore we create a span element inside the hyperlink using the class screenreader, which we have introduced before to mark elements for being invisible to sighted users to be read by screen readers only.
Alternative text for symbol fonts – Font Awesome: Here is another example. We are using the Font Awesome font library here. In this example, we are creating our alternative description using the aria-label attribute. The screen reader will use the value of this attribute to read the alternative text to the user. To hide the symbol itself from the screen reader, we use the aria-hidden attribute, so the screen reader only detects the alternative description and does not get confused by the graphic.
Whichever approach you prefer, both of these solutions work for adding alternative texts to graphics created with the help of symbol fonts.
As we have seen before, a screen reader can display a list of all the links on a web page. Therefore, the content of the hypertext links should be descriptive.
Here is a bad example: Using this example, a screen reader would present a list with three items all named 'click here'. A user will have no possibility to differentiate them.
A better approach would look like this… Each link has a unique content, which makes it easier to interpret their meaning when presented in a list.
Many users navigate web pages using the keyboard rather than the mouse. Expert users prefer keyboard commands for efficiency, while users with certain disabilities have no choice but to use the keyboard.
For example, people with physical impairments have difficulties with the fine motor movements required to use a mouse; users with visual disabilities rely on screen readers and cannot see where to click the mouse.
In contrast to mouse based navigation, keyboard navigation works sequentially. Users must tab through all focusable elements, typically links and form controls, one by one before reaching an element of interest.
To test a web page for keyboard accessibility quickly, just open a web page and press the Tab key. You should reach the first focusable element on the screen. By pressing the Tab key again, you should reach the next focusable element. By pressing Shift+Tab, you should reach the previous focusable element. Typically the tabbing follows the sequence in the HTML code.
The tabindex attribute explicitly defines the navigation order for focusable elements within a page. It can also be used to define whether elements should be focusable or not. If an element should be placed in the default navigation order, use a tabindex value of 0. To remove an element from the default navigation flow, for example a modal dialogue box, use a value of -1. Numeric tabindex values greater than 0 define the sequence used for keyboard navigation.
Keyboard navigation – CSS focus: Developers often highlight their links when moving the mouse pointer over them by using the :hover style selector. This makes it easier to detect links. The same is valid for keyboard navigation. However, as keyboard navigation does not use a mouse, a :hover style selector is not triggered. Keyboard navigation requires a :focus style selector. Use both style selectors to cover the 2 application scenarios.
Access keys: HTML offers the accesskey attribute to define shortcut keys to activate an element. Access keys are often discussed. Some people like them, others think they are useless. Arguments against:
- The user needs to know the access keys, so a website needs documentation explaining the access keys.
- Different websites use different access keys: there is no standard to define what kind of functionality should be reachable with which access key.
- An access key value can conflict with system or browser keyboard shortcuts, or with assistive technology functionality.
- The way to access the shortcut key varies in different browsers and operating systems. Firefox uses Alt + Shift + access key on Windows, and Control + Alt + access key on macOS, whereas Chrome uses the Alt key + access key on Windows, and Control + Alt + access key on macOS. Different browsers therefore show different behaviours.
Although there are a lot of arguments against access keys, there are some benefits. If you use a website often and you do know the access key values, then you can significantly speed up your operations. Therefore, developers of websites offering a working platform for daily use should consider including access keys.
We open a web page with two simple links. We use the Tab key to get to the first link. We press Space to open the web page behind it. We go back to the first page and navigate again to the first link. Now we would like to go to the next link by pressing the Tab key again. Oops… The keyboard event on the first link was used to change the behaviour on all types of key presses, including the Tab key. By changing the default keyboard behaviour, the Tab navigation was broken.
Let's have a look at the source code. As we can see in the code, the keydown trigger was used to catch all keyboard events, independently of the type of pressed key.
Here is another example. We have a simple form with 3 input fields. We press the Tab key and reach the first input field. We press the Tab key again to reach the second input field. We press the Tab key again. And again. And again. We cannot leave the second field. The Tab navigation is broken.
Let's have a look in the source code. The onblur event is triggered when the cursor tries to leave the input field, but the focus directive repositions the focus, and therefore the cursor, to the same input field, which causes an endless loop. Whatever the programmer's intention was, he broke the keyboard navigation.
Please avoid changing the default navigation behaviour. This often results in conflicts with assistive technologies.
When working with tabs, modal dialogue boxes and other more advanced user interface elements, use the focus() directive to position the cursor at an appropriate element in the new view. When that view is closed, return the focus to where it was before opening the view. This is a little abstract, so let's see how it works practically.
We have a web page with a button. When we click the button with the mouse, a dialogue box opens and asks for confirmation. Let's try to do the same with a screen reader.
[Screen reader:] Buy More Printer Ink button.
[Narrator:] We can open the dialogue box, but we cannot use it.
[Screen reader:] Link, another link. Link, and another link.
[Narrator:] The cursor is still located at the button that opened the dialogue box. We dig into the source code. We see the page content and the modal dialogue box. When we click the button, the confirm function is called.
The confirm function makes the dialogue box visible. We want to position the cursor inside this box, so we uncomment this line. The dialogue box will close when the user presses “OK” or “Cancel”. Whichever button we activate, the closeDialogue function will be called, which makes the dialogue box invisible again, so we reposition our cursor back to the button that was used to open the dialogue. Let's try it. We press the Tab key and open the dialogue box by pressing the Space key.
[Screen reader:] Buy More Printer Ink button. Are you sure you can afford it? OK Cancel web dialogue. OK button.
[Narrator:] Our cursor is repositioned inside the dialogue box. We can select our choice using the Tab key.
[Screen reader:] Cancel button.
[Narrator:] We activate 'Cancel' by pressing the Space key.
[Screen reader:] Buy More Printer Ink button. Link, another link.
Forms are used to collect user input. Form elements allow different data types to be entered, such as text fields, checkboxes, radio buttons and submit buttons. Here are some hints on how to improve the accessibility of forms.
Here is a bad example showing how missing accessibility can ruin the user experience. A screen reader will detect the table and read all the paragraphs in the first column followed by all the input fields in the second column. The user will probably not associate the items on the left with the input fields on the right as there is no information combining these elements.
If the user presses the Tab key to navigate through focusable elements, it gets even worse. The user will reach the different input fields without any information on what kind of data should be entered. Therefore, we need to find a way to add a label to an input field, which will always be read when the screen reader cursor reaches this input field.
We can describe the data to be entered for an input field with the help of a label. Here is an example of an explicit form label. The label is a visible element that can be styled like any other element. The for attribute of the label references the id attribute of the input field.
When the screen reader cursor reaches the input field, it will read the label in combination with the input element. We can do the same using implicit labels. In this case, we embed the input field inside the label element.
If you want to give the user even more information, you can use one of the HTML 5 input types, which can describe the type of the expected data, such as a date. Here is a list of the HTML 5 input types.
Please note that, at the time of creating this course, not all of the input types have a user interface implementation on all browsers. Older browsers in particular might not use any of these input types. So please test if a specific feature can be used for your application scenario.
Web pages may offer content in more than one language. If not otherwise defined, texts are always spoken using a default language, which is often the language of the operating system. Therefore, a developer should always declare the primary language of a web page in the lang attribute of the html element.
Language information should be declared using a BCP 47 language code. BCP stands for Best Current Practice. BCP 47 allows extended language codes to be set. This allows us, for example, to differentiate between British English and American English. In our code example we have chosen British English. You will find a link to the BCP 47 language codes under the Documents link on the platform.
We can mark parts of a web page to use a different language than the primary one. Please note that a screen reader requires a matching voice to speak the text using the correct pronunciation.
As a user has to install this voice on their client machine, there is not much a developer can do from the server side to support them other than declaring the correct language. For some of the less commonly used languages, there might be no voice available, such as Luxembourgish. A user might then choose an alternative voice using a language with similar pronunciation.
In recent years, more and more voices for a multitude of different languages have been made available to the screen reader user community, so this problem might be resolved in the near future.
Accessible Rich Internet Applications
Today's web pages are more and more interactive. Web documents use dynamic elements that change their appearance on user interaction. Web user interfaces mimic those of desktop systems more and more. These user interface controls and content updates are often not accessible to users with disabilities, especially screen reader users and users who cannot use a mouse or other pointing device. This is where the Web Accessibility Initiative – Accessible Rich Internet Applications standard, WAI-ARIA or ARIA for short, comes in.
ARIA allows web pages to declare themselves as applications rather than as static documents, by adding role, property, and state information. Let's see how this information is encoded.
Roles can be interpreted as promises, which declare the type of a user interface element. The code line does not only tell us that the item is part of a list. It also tells us that this item is part of a menu. A role is declared using the ARIA role attribute. Please do not enter any value in this attribute. The possible values are precisely defined by the ARIA standard. Depending on the role value, a screen reader will behave differently.
Properties contain attribute values, which will not be modified after page loading. They are static and often describe relationships with other elements. We have seen ARIA properties before.
Landmark roles: We have seen landmark roles before as an example of roles. One of the easiest ARIA features to implement, and one that provides significant immediate benefits to screen reader users, is landmark roles.
There are eight landmark roles, each representing a block of content that commonly occurs on web pages. Be careful when using the application role. When assistive technologies encounter content marked with the application role, they stop listening for users’ keystrokes and hand off all functionality to the application. If you do not know when to use this role, then just avoid using it.
There is a ninth landmark role. The region landmark role is used to mark an area in the document that the author has identified as significant. It is used to provide a generic landmark when none of the other landmark roles are appropriate.
If a landmark role is used more than once on a page, the aria-label attribute should be used to distinguish between the two regions.
Many HTML semantic elements have an implicit ARIA role. So, please, avoid redundant information; for example, a header HTML element does not need an additional header ARIA role attribute. You could also damage your code with contradictions; for example, a button HTML element has an implicit ARIA role of button. So do not assign a different role to a button as it may produce undefined results.
HTML 5 elements and landmark roles: Several HTML 5 sectioning elements automatically create ARIA landmark regions.
- The header element includes the banner role when in the context of the body element.
- The nav element includes the navigation role.
- The main element includes the main role and should only be used once per web page.
- The footer element includes the contentinfo role when in the context of the body element.
- The aside element includes the complementary role.
- The form element includes the form role when it has an accessible name using the aria-labelledby, aria-label or title attributes.
- The section element includes the region role when it has an accessible name using the aria-labelledby, aria-label or title attributes.
Native HTML elements: Often developers use generic divs and spans to build a web page. Web WYSIWYG editors in particular tend to follow this strategy as it makes automatic code generation much easier. However, this should be avoided. Always use native HTML tags instead of generic divs and spans.
Screen readers cannot identify generic divs or spans as interactive controls because their behaviour was added by scripting. When reaching a native HTML element, the screen reader executes a defined user interface behaviour associated with it.
Additionally, generic divs or spans are not focusable, so they cannot be activated with the keyboard. As previously introduced, we can reestablish this behaviour by adding a tabindex value. So, although this code is not elegant, it would work.
Complex user interface elements: Today’s web technology allows the building of user interfaces, which mimic those of desktop systems more and more. The more complex this kind of user interface gets, the higher the risk that web developers create inaccessible web interfaces.
Let's have a look at a code creating a tab user interface. Here is a possible, but totally inaccessible, code solution. The tab itself is made up of a list presenting the menu. The content part below is created by a div container including sub-divs. The visibility of the sub-divs is switched on or off via scripting activated by the selection of the according tab. Let's try this code with a screen reader.
[Screen reader:] Expanded link, Home. Collapsed link, Profile. Collapsed link, Contact. This is the text of the first tab presenting some information about Home. Collapsed link. Collapsed link. Expanded link, Profile. Collapsed link. This is the text of the second tab presenting some information about Profile. Collapsed link, Contact. Expanded link, Contact.
[Narrator:] Mmmh… There is no information that could help the user to detect that this is a tab interface and what roles the different elements have. When we look at this code, how could a screen reader detect that this is a tab user interface? There is no information inside the code describing the purpose of these elements. Here comes the ARIA standard to the rescue. ARIA provides a way to add the missing semantics needed by assistive technologies.
Let's look at this code. By adding a few roles and some label information, the context of the user interface becomes clearer. A screen reader knows the meaning of these roles and can act accordingly. Let's try this code with a screen reader.
[Screen reader:] The Tab based menu tab group. Home, selected expanded tab, 1 of 3. Profile, collapsed tab, 2 of 3. Profile, expanded tab, 2 of 3. The tab based menu tab group. Profile tab panel. This is the text of the second tab presenting some information about Profile. Profile tab panel. End of the tab based menu tab group. Home selected, collapsed tab, 1 of 3. Profile expanded tab, 2 of 3. Contact collapsed tab, 3 of 3. Contact expanded tab, 3 of 3. The tab based menu tab group. Contact tab panel. This is the text of the third tab presenting some information about Contact.
[Narrator:] This is much better.
Accessible frameworks and libraries: The tab interface we saw before is just one of many possible interfaces that can be built with ARIA roles. This course is too short to introduce them all. Most of the time a developer will not build these user interfaces from scratch.
Bootstrap: Bootstrap is an open source toolkit for developing responsive, mobile-first projects on the web. It can be downloaded for free using the URL getbootstrap.com. You can find the documentation on how to use Bootstrap under the Documents tab on the platform.
We want to look at an example on how to build an accordion. We can find this under Components, Collapse, and then Accordion example. We can see a working example as part of the documentation. An accordion is a vertically stacked set of interactive headings that each contain a title representing a section of content. The headings function as controls that enable users to reveal or hide their associated sections of content. Accordions are commonly used to reduce the need to scroll when presenting multiple sections of content on a single page.
Let's look at the code. This is the first heading. This is the related content part. It is followed by the next heading and the next content. As the first section is open by default, the value of the aria-expanded attribute is true. The aria-controls attribute refers to the id of the related content part collapseOne. The content part marks that its label is defined by the element with the aria-labelledby attribute value of headingOne. All data and style attribute values are related to the Bootstrap framework itself. They build the interface to the library.
Operating systems and web browsers: We have some remarks to add related to operating systems and web browsers. Although there are standards, there is room for interpretation in different situations. Different browsers on different operating systems in combination with different assistive technology solutions and products might behave differently. Be sure to test your solution using more than one operating system and browser.
There are free screen readers available that allow you to test your code in different environments without buying expensive licenses. Do not forget to test your website with keyboard based navigation.
Keep your operating systems and browsers up to date. This increases the chance that problems have been fixed and new standard features have been added.
Where to continue?
You have seen an introduction on how to code accessible web pages. This course does not claim to offer a complete reference or to provide a solution for every possible scenario, but we hope we have given you a good start.
Depending on your personal interests, you could continue with the following chapter: HTML testing.
[Automated voice:] Accessibility. For more information visit: op.europa.eu/en/web/accessibility.