Chapter 1. Structuring Documents
This book focuses on writing accessible components, but accessibility begins at the very first line of your HTML document. Your components live on a page, and your page is part of a document. Several elements, especially in the <head>
of your document, affect accessibility.
1.1 Define the Natural Language
Problem
If a page doesn’t contain an explicit definition of the natural language it’s written in, software may not be able to translate content correctly. The term natural language refers to the language you use for the content on the page, not the programming language. This lack of information can result in faulty translations, wrong formatting, and content being hard to understand for screen reader users.
Solution
You can define the natural language of a page by using the lang
attribute on the <html>
element. See Example 1-1.
Example 1-1. English defined as the natural language of the page
<!DOCTYPE html>
<
html
lang
=
"en"
>
</
html
>
You can also define a specific dialect of the base language. See Example 1-2.
Example 1-2. British English defined as the natural language of the page
<!DOCTYPE html>
<
html
lang
=
"en-GB"
>
</
html
>
The lang
attribute is global, meaning you can use it on any element, although it may not affect some of them. It can be helpful if a page is written in one language but contains text passages or even single words in other languages. See Example 1-3.
Example 1-3. Transliterated Japanese in Latin script used on a page written in English
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
></
head
>
<
body
>
<
p
>
The Wind-Up Bird Chronicle (<
span
lang
=
"ja-Latn"
>
Nejimakidori Kuronikuru</
span
>
) is a novel published in 1994 by Japanese author Haruki Murakami.</
p
>
</
body
>
</
html
>
Use the lang
pseudoclass to adjust the typography and layout for specific languages. See Example 1-4.
Example 1-4. Selecting all elements in the Serbian language
:lang
(
sr
)
{
font-family
:
'Cyrillic font'
,
sans-serif
;
}
Discussion
Assistive technology and other software may not be able to determine the natural language of a page automatically. Certain features in HTML and Cascading Style Sheets (CSS) rely on that information to help localize software content and provide an excellent overall user experience. You must set the language of each page programmatically and explicitly by using the lang
attribute on the <html>
element, as shown in Example 1-1. For passages of text written in a different language than the primary language of the page, you can also use the attribute, as shown in Example 1-3. That allows screen readers to improve pronunciation by switching voice profiles accordingly for certain words or sentences. Try to do this sparingly because switching voice profiles can be annoying because it interrupts the reading flow. For well-established foreign words, it might not be necessary. Examples in German are English words like “Download,” “Workshop,” or “Link.”
Usage
The value of the lang
attribute must be a valid BCP 47 language tag, composed from one or more subtags. A subtag is a sequence of alphanumeric characters distinguished and separated from other subtags by a hyphen.
The language subtag is a 2- or 3-character code that defines the primary language: for example, en
for English, de
for German, or fr
for French, as shown in Example 1-5.
Example 1-5. Spanish defined as the natural language of the page
<
html
lang
=
"es"
></
html
>
The optional script subtag is a 4-character code that defines the writing system used for the language, as shown in Example 1-6.
Example 1-6. A name in Cyrillic script next to the same name in Latin script marked as such
Никола Јокић (<
span
lang
=
"sr-Latn"
>
Nikola Jokić</
span
>
).
The optional region subtag is usually a 2-character country code written in all caps and defines a dialect of the base language, as shown in Example 1-7.
Example 1-7. Austrian German defined as the natural language of the page
<!DOCTYPE html>
<
html
lang
=
"de-AT"
>
</
html
>
You should use the 2-character primary language code and add region subtags only when it is necessary to differentiate content in different dialects that may not be mutually understandable. At least for screen reader users, not adding region subtags shouldn’t make a difference because they’re typically ignored by the software.
You can find a list of all tags and subtags in the BCP 47 language subtag lookup.
Benefits
The lang
attribute is powerful and affects many aspects of web accessibility and user experience in general. These include:
Assistive technology
Speech synthesizers that support multiple languages adapt their pronunciation and syntax to the language of the page, speaking the text in the appropriate accent with proper pronunciation. For a page with German content where the language of the page is set to English (lang="en"
), the screen reader software may pick an English synthetic voice profile and read the German text with English pronunciation. If you set no language, screen readers may fall back to the users’ default system setting, which might not be appropriate. The result can be hard to understand, confusing, or even completely wrong. All screen readers support numerous languages. Some software switches language automatically, while for others users have to install and configure language voices or packs manually.
The attribute definition also allows Braille translation software to optimize the output and prevent it from erroneously creating Grade 2 Braille contractions.
Translation
Translation tools like Google Translate use the information from the lang
attribute to translate content on the page. While this kind of software is usually good at automatically detecting the language of the page, a mismatch between the actual language and the defined language can yield unexpected and unwanted translations.
Quotes
Quotation marks may change depending on the natural language of the page. For example, English uses different quotation marks than German or French, and the correct lang
helps browsers pick the proper glyphs, as illustrated in Examples 1-8, 1-9, and 1-10.
Example 1-8. Automatic quotation marks using the <q>
element in English
<
p
lang
=
"en"
>
<
q
>
A quote in English.</
q
>
</
p
>
<!-- Results in: “A quote in English.” -->
Example 1-9. Automatic quotation marks using the <q>
element in German
<
p
lang
=
"de"
>
<
q
>
Ein Zitat auf Deutsch.</
q
>
</
p
>
<!-- Results in: „Ein Zitat auf Deutsch.“ -->
Example 1-10. Automatic quotation marks using the <q>
element in French
<
p
lang
=
"fr"
>
<
q
>
Une citation en français.</
q
>
</
p
>
<!-- Results in: « Une citation en français. » -->
Hyphenation
lang
may affect hyphenation in CSS. See Example 1-11.
Example 1-11. A paragraph with a maximum width of 28 characters and hyphenation turned on
p
{
max-width
:
28ch
;
hyphens
:
auto
;
}
In Examples 1-12, 1-13, and 1-14, you can see how the same paragraph written in German, given a different lang
attribute value, renders differently in Google Chrome. Words either don’t break at all or break at different positions. Only the first and the second examples are correct. It’s worth noting that browsers behave differently.
Example 1-12. Correctly hyphenated German text in a paragraph defined as German
<
p
lang
=
"de"
>
Weit hinten, hinter den Wortbergen, fern der Länder Vokalien und Konsonantien leben die Blindtexte. Abgeschieden wohnen sie in Buchstabhausen an der Küste des Semantik, eines großen Sprachozeans. Ein kleines Bächlein namens Duden fließt durch ihren Ort und versorgt sie mit den nötigen Regelialien.</
p
>
<!-- Results in:
Weit hinten, hinter den Wortbergen,
fern der Länder Vokalien und Konso-
nantien leben die Blindtexte. Abge-
schieden wohnen sie in Buchstab-
hausen an der Küste des Semantik,
eines großen Sprachozeans.
-->
Example 1-13. No hyphenation of German text in a paragraph defined as English
<
p
lang
=
"en"
>
Weit hinten,…</
p
>
<!-- Results in:
Weit hinten, hinter den Wortbergen,
fern der Länder Vokalien und
Konsonantien leben die Blindtexte.
Abgeschieden wohnen sie in
Buchstabhausen an der Küste des
Semantik, eines großen
Sprachozeans.
-->
Example 1-14. Wrong hyphenation of German text in a paragraph defined as French
<
p
lang
=
"fr"
>
Weit hinten,…</
p
>
<!-- Results in:
Weit hinten, hinter den Wortbergen,
fern der Länder Vokalien und Konso-
nantien leben die Blindtexte. Abges-
chieden wohnen sie in Buchstabhau-
sen an der Küste des Semantik, eines
großen Sprachozeans.
-->
Font selection
Browsers may select language-appropriate fonts for displaying details in ideographic characters that vary from language to language, such as Chinese, Japanese, and Korean (known as the “CJK languages.”)
1.2 Describe the Document
Solution
You can name pages using the <title>
element in HTML. The title must be unique and must describe the topic or purpose of each page concisely. See Example 1-15.
Example 1-15. A succinct and descriptive page title
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
title
>
Products - Johanna’s Toy Store</
title
>
</
head
>
</
html
>
For social media previews, you can optionally use an open graph meta
tag to include more or different information, as shown in Example 1-16.
Example 1-16. A catchier page title for social media previews
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
title
>
Products - Johanna’s Toy Store</
title
>
<
meta
property
=
"og:title"
content
=
"Find dolls, toy cars, and more in Johanna's Toy Store"
>
</
head
>
</
html
>
Adding context depending on the state of the page can be helpful (see Examples 1-17, 1-18, 1-19, and 1-20).
Example 1-17. The title includes the current step and the total number of steps in a checkout process
<
title
>
Checkout (step 3 of 4) - Johanna’s Toy Store</
title
>
Example 1-18. Number of validation errors in the title of a sign up page
<
title
>
2 errors - Sign Up - Johanna’s Toy Store</
title
>
Example 1-19. Number of results in a search page’s title
<
title
>
21 results for term “crocodile” - Johanna’s Toy Store</
title
>
Example 1-20. The title indicating the current search results page
<
title
>
Page 2 - Product Search Results - Johanna’s Toy Store</
title
>
Discussion
Sometimes it takes work to get oriented on a website, such as when users land on a page coming from an external resource like a search engine or if page changes happen unexpectedly or unannounced. That’s especially true for single-page applications (SPAs), where page navigation works differently from most sites.
The page’s title is one of the essential elements in an HTML document, and users benefit from a well-formed and descriptive page title.
Screen reader users can use shortcuts to announce the page title. For example, if they click a link in an SPA and content changes, but there’s no announcement that changes have happened, they can use a shortcut to get oriented and check if they’ve landed on a different page. You can try it yourself by using one of the shortcuts in Table 1-1.
Screen reader | Command | Announcement |
---|---|---|
JAWS |
|
Page title |
NVDA |
|
Page title |
VoiceOver macOS |
|
Page summary, including page title |
VoiceOver macOS |
|
Page title |
Note
By default, VO
stands for the combination of pressing Control
and Option
at the same time in VoiceOver on macOS. Alternatively, you can map VO
to Caps Lock
in the VoiceOver Utility settings.
There are other reasons for writing good page titles: they serve as labels for bookmarked pages/favorites, and search engines use the title in their results pages. Social media sites, chat and mail applications, and similar software use the title in link previews when no other title is specified. Please note that the open graph meta tag shown in Example 1-16 is no alternative to the <title>
element. Whether a site or application interprets the open graph title is up to the site. Ideally, the native title’s content should be good enough to serve all purposes.
There are several best practices you should follow when writing page titles:
The title must be unique
The <title>
serves as the label in tabs or browser windows. Unique titles help to distinguish one page from the other if multiple tabs of the same site are open. A common issue is that the title is the same on all pages (see Example 1-21). The result is shown in Figure 1-1.
Example 1-21. Bad practice: Three different pages with the same title
<!-- products.html -->
<
title
>
Johanna’s Toy Store</
title
>
<!-- team.html -->
<
title
>
Johanna’s Toy Store</
title
>
<!-- contact.html -->
<
title
>
Johanna’s Toy Store</
title
>
Use unique titles to communicate the purpose of the page and improve orientation (see Example 1-22 and the result in Figure 1-2).
Example 1-22. Three different pages, each with a unique title
<!-- products.html -->
<
title
>
Products - Johanna’s Toy Store</
title
>
<!-- team.html -->
<
title
>
Our Team - Johanna’s Toy Store</
title
>
<!-- contact.html -->
<
title
>
Get in Touch - Johanna’s Toy Store</
title
>
That applies to websites with multiple pages but also to SPAs. You might have to take extra steps in an SPA, but if the user navigates to a different route, the page title must change as well. Hidde De Vries explains how to do that in “Accessible page titles in a Single Page App”.
The title should be concise
The title should be concise and should accurately describe the purpose of the page. It’s the first information a screen reader user gets when they’re accessing a page. They don’t need a detailed summary of the page’s content, but a succinct description.
Another reason to constrain the length of the title is that it usually gets cut off in search result pages at a certain character length (approximately 50 to 60 characters).
The relevant information comes first
The title should start with the page’s name, followed by the name of the site, company, or organization, as shown in Example 1-15. Putting the relevant information first reduces repetition for screen reader users who visit multiple pages on a site, because they get the unique page-specific details first. This way of arranging content makes scanning and identifying pages easier when numerous tabs are open, as shown in Figure 1-3.
Don’t put the organization’s name first (as in Example 1-23) because the relevant information might get cut off, as you can see in Figure 1-4.
Example 1-23. Bad practice: Name of the site followed by the name of the page
<
title
>
Johanna’s Toy Store - Products</
title
>
Context-dependent information
Sometimes it’s helpful to add context or additional information. For example, if you split a page into multiple steps, the title should include the current step. Example 1-17 shows the title of the third of four steps in a checkout process. If there are validation errors in a form, you can indicate the number of errors (see Example 1-18). For search result pages, you can add the number of results or the current page, as shown in Examples 1-19 and 1-20.
1.3 Set the Viewport Width
Solution
Configure the viewport
meta tag in a way that allows for the most flexibility. Avoid restrictive settings.
The meta
tag in Example 1-24 works for most websites and web apps. It’s all you need to configure viewport settings to build a flexible, adaptive, responsive website.
Example 1-24. The page uses the available width of the device as the width for the viewport
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1"
>
There are specific properties or values you should avoid.
Setting the value of the width
property to anything other than device-width
can cause problems. If the defined width of the viewport is larger than the available width on the screen, content may overflow, resulting in horizontal scroll bars. Example 1-25 applies an explicit viewport width.
Example 1-25. Bad practice: Width of the viewport set to an absolute value
<
meta
name
=
"viewport"
content
=
"width=500, initial-scale=1"
>
maximum-scale
allows you to limit the maximum zoom level, which is 10
by default in most browsers. If you set it to 1
, you’re disabling zoom in some browsers (see Example 1-26).
Example 1-26. Bad practice: Zoom disabled by setting the maximum scale to 1
<
meta
name
=
"viewport"
content
=
"width=device-width, maximum-scale=1, initial-scale=1"
>
The setting user-scalable
defines whether zooming is allowed. Setting it to no
or 0
disables zoom, as shown in Example 1-27.
Example 1-27. Bad practice: Zoom disabled by setting user-scalable
to “no”
<
meta
name
=
"viewport"
content
=
"width=device-width, user-scalable=no, initial-scale=1"
>
Discussion
Users must be able to customize their browsing experience based on their preferences and needs. Browsers offer different settings and features to support that. The ability to set larger font sizes or zoom in on the page is essential, but many websites disallow zooming on handheld devices.
Before responsive web design became a thing, websites were designed for large viewports, often using fixed width values like 960px
or 1024px
for the body or main content of the page. With the rise of smartphones and other handheld devices, this became a problem because pixel widths of the screens on these devices were usually much smaller than 960px
. The initial containing block, the rectangle in which the root element (<html>
) lives, has the dimensions of the viewport. If the page is larger than the viewport, this can result in unintended layout wrapping, clipped content, and unpleasant scrollable bounds. That’s why mobile browsers generally use a fixed width (typically 980px
to 1024px
) for the initial containing block. The resulting layout is then scaled down to fit the available screen space. That mitigates the issues, but it also means that the CSS pixel size on these pages will be much smaller, forcing users to zoom in.
On responsive websites, that’s not an issue, since they’ve been built to work well on assorted viewports. However, you have to change the fixed width of the containing block on mobile devices to a width relative to the viewport’s dimensions to work well with responsive designs. You can do that by using the viewport meta
tag, as illustrated in Example 1-24.
width=device-width
sets the viewport’s width to the device’s available width.
initial-scale=1
ensures that the default zoom level is at 100%. This might not always be the default in all browsers. That’s why I recommend setting it explicitly.
The fact that a page is responsive and optimized for small viewports doesn’t mean users won’t want to zoom. Adrian Roselli lists several reasons the ability to zoom is essential in his article “Don’t Disable Zoom”:
-
The text may be too small for the user to read.
-
The user may want to see more detail in an image.
-
Selecting words to copy/paste may be easier for users when the text is larger.
-
The user wants to crop animated elements out of the view to reduce distraction.
-
The developer did a poor job of responsive design, and the user needs to zoom just to use the page.
-
There is a browser bug that causes the default zoom level to be odd.
-
It can be confounding for users when the browser interprets a pinch/spread gesture as something else.
Websites disabling zoom is a prevalent issue. According to the Accessibility chapter of the 2022 Web Almanac, 23% of desktop home pages and 28% of mobile home pages attempt to disable zoom. The report’s author uses the term attempt, because some browsers, like Safari on iOS or Samsung Internet on Android, ignore the maximum-scale=1
and user-scalable=no
properties. Chrome and Firefox don’t, but users can force zoom in their browser settings. In Firefox, find the browser settings, select “Accessibility,” and activate “Zoom on all websites.” In Chrome, find the browser settings, select “Accessibility,” and check “Force enable zoom.”
Justified reasons to disable zoom
On the average website, there’s no good reason to turn off zoom. The same applies for app-like websites that resemble native apps. There are rare exceptions where the gestures for zooming would interfere with the website’s functionality. An example would be a site that contains only an interactive map. If that’s the case, it might be okay to disable the native zoom feature, but you must provide an alternative custom solution.
1.4 Optimize Rendering Order
Problem
The head of a document can contain various elements that serve different purposes: meta tags, scripts, links to other resources, and more. They can be in any order, but certain elements should come before others to ensure good loading performance. Inefficient asset loading prevents users from obtaining information quickly, if at all.
Solution
Web performance expert Harry Roberts suggests a specific order of elements within the <head>
to ensure the best possible loading strategy, as shown in Example 1-28.
Example 1-28. The ideal order of elements in the <head>
<
head
>
<!-- Character encoding -->
<
meta
charset
=
"UTF-8"
>
<!-- Viewport meta tag -->
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1"
>
<!-- CSP headers -->
<
meta
http-equiv
=
"Content-Security-Policy"
content
=
"upgrade-insecure-requests"
>
<!-- Page title -->
<
title
>
Johanna’s Toy Store</
title
>
<!-- preconnect -->
<
link
rel
=
"preconnect"
href
=
"#"
/>
<!-- Asynchronous JavaScript -->
<
script
src
=
""
async
></
script
>
<!-- CSS that includes @import -->
<
style
>
@
import
"file.css"
;
</style>
<!-- Synchronous JavaScript -->
<
script
src
=
""
></
script
>
<!-- Synchronous CSS -->
<
link
rel
=
"stylesheet"
href
=
"#"
>
<!-- preload -->
<
link
rel
=
"preload"
href
=
"#"
/>
<!-- Deferred JavaScript -->
<
script
src
=
""
defer
></
script
>
<
script
src
=
""
type
=
"module"
></
script
>
<!-- prefetch / prerender -->
<
link
rel
=
"prefetch"
href
=
"#"
/>
<
link
rel
=
"prerender"
href
=
"#"
/>
<!-- Everything else (meta tags, icons, open graphs, etc.) -->
<
meta
name
=
"description"
content
=
""
>
</
head
>
Discussion
There are different fields within web design and development, like accessibility, usability, user experience, performance, and security. They all focus on different things, but they’re not mutually exclusive. Accessibility, for example, overlaps with all of them. Improving the accessibility of form fields may result in a better user experience for everyone. If a website loads slowly, it affects users’ experience and accessibility. A website that loads for too long or not at all on a slow connection is not accessible. Designing and building accessible websites means creating inclusive experiences without barriers that prevent people from interacting with the web. These barriers include physical, temporary, and situational disabilities and socioeconomic restrictions on hardware, bandwidth, and speed.
Getting the order of elements in the <head>
right affects performance in general, but it also affects the rendering of specific elements that may contain critical information for users of assistive technology. HTML is parsed line by line, which means that a browser doesn’t know that line 4 exists when line 3 hasn’t finished parsing. If something blocks rendering early in a document, subsequent lines have to wait until the browser has finished parsing preceding lines. That makes the correct order of elements in the <head>
crucial to web performance and accessibility.
Performance experts suggest several rules and optimizations, including:
-
If something doesn’t have to be in the
<head>
, remove it or put it in the<body>
. That includes low-priority scripts, redirects, or any unnecessary payload. -
Self-host as much as possible and don’t rely on third-party content delivery networks (CDNs). Harry Roberts explains why in his article “Self-Host Your Static Assets”.
-
Validate your HTML code, because invalid elements in the
<head>
can cause performance problems. -
Metadata about the page, like character encoding and information about the viewport, go first.
-
Nothing render-blocking must come before the
<title>
. -
Synchronous JavaScript comes before CSS, because CSS blocks the execution of subsequent JavaScript.
-
Avoid
@import
in CSS. -
SEO and social meta tags go last.
Harry Roberts has created a CSS file called ct.css, also available as a bookmarklet, that you can use to run tests against your <head>
elements (see Figure 1-5).
1.5 Structure the Document
Solution
Use landmarks: regions that represent the organization and structure of a web page. They usually identify areas the user may want to access quickly.
Chapter 2, “Structuring Pages” focuses on page regions, but there are also common landmarks you will use across your site, like <header>
, <main>
, and <footer>
. Every element in the page should be within one of these landmarks, as shown in Example 1-29.
Example 1-29. An exemplary structure of a web page
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
<
title
>
Products - Johanna’s Toy Store
<
/
title
>
<
/
head
>
<
body
>
<
header
>
<
a
href
=
"/"
>
Johanna’s Toy Store
<
/
a
>
<
nav
aria-label
=
"Main"
>
<
ul
>
<
li
>
<
a
href
=
"/home"
>
Home
<
/
a
>
<
/
li
>
<
li
>
<
a
href
=
"/products"
aria-current
=
"page"
>
Products
<
/
a
>
<
/
li
>
<
li
>
<
a
href
=
"/team"
>
Team
<
/
a
>
<
/
li
>
<
li
>
<
a
href
=
"/contact"
>
Contact
<
/
a
>
<
/
li
>
<
/
ul
>
<
/
nav
>
<
form
role
=
"search"
>
<
label
for
=
"search"
>
Search
<
/
label
>
<
input
type
=
"text"
id
=
"search"
>
<
/
form
>
<
/
header
>
<
main
id
=
"content"
>
<
h1
>
All products
<
/
h1
>
<
/
main
>
<
footer
>
©
2024
<
/
footer
>
<
/
body
>
<
/
html
>
Discussion
Using semantic elements within components and regions of a page is the foundation of any accessible website, but users can benefit from larger semantic groups, too. The page must communicate how it’s structured and group common sitewide and page-specific elements. Landmarks in HTML help with that.
You can define landmarks with the appropriate HTML elements or use the role
attribute when no element exists. The elements in Example 1-30 are semantically the same.
Example 1-30. Two banner landmarks
<!-- <header> with an implicit banner role -->
<
header
></
header
>
<!-- <div> with an explicit banner role -->
<
div
role
=
"banner"
></
div
>
Tip
Most semantic elements in HTML convey two bits of information: their accessible role and an accessible name. The role defines what kind of element it is: a button, link, image, etc. The accessible name is text by which software can identify a component, coming from the element’s text content, another associated element like <label>
, or an attribute like aria-label
, aria-labelledby
, alt
, or title
.
Follow the first rule of Accessible Rich Internet Application (ARIA) use and prefer elements with implicit roles over using the role
attribute if browser support allows it. Older browsers and screen readers that don’t support elements with implicit landmark roles once needed the additional explicit role, as shown in Example 1-31, but specifying both isn’t necessary anymore.
Example 1-31. <header>
with an additional explicit banner role
<
header
role
=
"banner"
></
header
>
There are different types of regions that serve other purposes in different contexts. Table 1-2 lists HTML elements, their corresponding ARIA roles, and the context in which they’re exposed as landmarks.
Element | ARIA role | Conditions |
---|---|---|
|
banner |
Only in context of the body element; not when it’s a descendant of |
|
navigation |
|
|
main |
|
|
region |
When it has an accessible name. |
|
form |
When it has an accessible name. |
|
search |
Or form with |
|
complementary |
|
|
contentinfo |
Only in context of the body element; not when it’s a descendant of |
Benefits
There are many reasons to use landmarks. The remainder of this section will explain several of those reasons in detail.
Navigation
Screen reader users can jump from landmark to landmark using keyboard shortcuts or gestures, which provide a convenient way to skip to specific areas without interacting with the rest of the page (see Table 1-3).
In VoiceOver on iOS, you can select the “landmark” option in the rotor, which provides you with direct access to certain elements on the page, and use the swipe up and down gestures to navigate between landmarks. In TalkBack on Android, you can set the reading controls to “landmarks” and swipe up and down to navigate. In NVDA on Windows, you can press D
or Shift
+ D
, and in JAWS on Windows, R
and Shift
+ R
to do the same (see Table 1-3).
Screen reader | Command |
---|---|
NVDA |
|
JAWS |
|
Narrator |
|
VoiceOver on iOS |
Rotor |
TalkBack on Android |
Reading controls |
It’s mostly screen reader users who benefit from having landmarks, but also browser extensions like “Landmark Navigation via Keyboard or Pop-up” add keyboard shortcuts to the browser, providing access to landmarks for non-screen reader users. See Figure 1-6.
Overview
Screen reader users can list all landmarks on a page and access them directly (see Table 1-4).
Screen reader | Command |
---|---|
NVDA |
|
JAWS |
|
VoiceOver on macOS |
Rotor |
Site-Specific Landmarks
The three most relevant main landmarks are <header>
, <main>
, and <footer>
.
banner landmark
The <header>
, with its implicit banner
role, contains mostly site-oriented rather than page-specific content. That’s typically a logo, skip links, the main navigation, secondary navigations, a search widget, and other content that is relevant and visible on every page.
Not every <header>
is a landmark. If it’s nested inside <article>
, <aside>
, <main>
, <nav>
, or <section>
, it’s semantically similar to a <div>
and not exposed as a landmark anymore. Having multiple header
elements on a page is fine, but you should add only a single banner
landmark.
Typically, you’ll find banner
landmarks at the beginning of the <body>
in the document. Visually, it’s usually at the top of the page. That is a common pattern but not a strict rule; it may also look like a sidebar. The position doesn’t affect its semantic purpose. Just because it’s located on the side doesn’t mean its role has to change.
main landmark
The <main>
element’s implicit main
role represents the page’s core content. There should be only one visible main element on a page, and its ancestors should be limited to html
and body
to guarantee a hierarchically correct structure. If necessary, it’s possible to wrap it in <div>
elements.
If you’re working with an SPA with multiple <main>
elements on a page, hide all the inactive ones, as shown in Example 1-32. Having more than one visible and reachable main landmark on a page might confuse users and result in them missing content because they usually expect only one per page.
Example 1-32. Multiple main
elements, but only one is visible
<
main
hidden
>
<
h1
>
Home</
h1
>
</
main
>
<
main
>
<
h1
>
Products</
h1
>
</
main
>
<
main
hidden
>
<
h1
>
Team</
h1
>
</
main
>
<
main
hidden
>
<
h1
>
Contact</
h1
>
</
main
>
contentinfo landmark
The <footer>
element’s implicit contentinfo
role also contains site-oriented content. That’s typically copyright data, secondary navigations, and other links.
Similar to the <header>
, the <footer>
is only a landmark in the <body>
context. If it’s nested inside <article>
, <aside>
, <main>
, <nav>
, or <section>
, it’s not a landmark anymore. Having multiple footer
elements on a page is fine, but you should add only a single contentinfo
landmark.
Get Web Accessibility Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.