HTML - Back to basics
Craig Abbott
Head of Accessibility, Digital
@abbott567
Did you know?
Under the Public Sector Bodies Accessibility Regulations 2018, it is illegal to push invalid HTML into a live public sector website or digital service.
The Web Content Accessibility Guidelines (WCAG) 2.1
To meet WCAG 4.1.1 Parsing, your HTML code must be valid. This means it must follow the rules laid out in the specification.
There’s a fundamental lack of respect for HTML as a language
Because most developers can make a page ‘look’ like the design, HTML and CSS are generally considered ‘easy’.
HTML is not studied as a specialism
In most computer science degrees, HTML is only covered in “full stack development”. The entire module is usually around 100 hours and covers things like:
- design principles
- information architecture
- authentication and authorisation
- security
- standards and compliance
- client and server-side coding
- usability and accessibility
HTML is flexible… Too flexible!
The following 3 examples are all valid.
But only one of them is correct.
<button class="button">Continue</button>
<a class="button" href="#">Continue</a>
<div class="button">Continue</div>
Although HTML is flexible, there are still rules!
The spec, or specification, are the rules of the language. It defines what you can and can’t do.
For example, you can’t just make up attributes to get your JavaScript to work, although many people do.
<div moo="cow">…</div>
<script>
div.getAttribute('moo') === 'cow'
</script>
Boiler plate templates are basic
Boilerplate ‘bare minimum’ templates often don’t even include a <main>
element.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Boilerplate HTML</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Page content -->
<script src="index.js"></script>
</body>
</html>
Boilerplate templates still expect you to know HTML
Unfortunately, a lot of people who use them, do so because they’re not 100% sure what then need to include.
Mozilla Developer Network (MDN)
MDN combines sources such as WCAG 2.1 and the HTML5 Spec into a more user-friendly document.
If you’re ever unsure on how an element or attribute works, MDN is a really good place to look it up!
Before we start
If you’re building digital services, you should use GOV.UK Design System and GOV.UK Frontend.
The components are tried and tested and are more likely to be accessible than building your own from scratch.
Let’s look at
- Common elements
- Headings
- Language
- Page titles
- Landmarks
- Skip links
Common elements
Each HTML element has a purpose. Choosing the correct elements is the easiest way to make anything accessible.
Paragraph element
A paragraph element (<p>
) is the simplest form of structured text. It is used for anything which is basic content and should be used when the content does not fit better into another category.
<p>
A paragraph is the simplest form of meaningful content.
</p>
Division element
The division element (<div>
) is a decorative element. It is used to wrap blocks of content to give you control over the design.
You should never use them for anything which is meaningful or interactive unless you modify their aria-role.
<div class="half-width">
<h2>Featured artists</h2>
…
</div>
Span element
The span (<span>
) element is also a decorative element, but they are used inline so you can wrap parts of a sentence to add stylistic choices.
Spans should never be used for anything interactive or meaningful and should only be used when styles do not add context.
<p>
Only 8% of the global population has <span class="blue">blue</span> eyes.
</p>
Emphasis element
The emphasis (<em>
) element should be used to emphasise certain words like you would in natural language. It should not be used simply to add italic styling.
<p>
You should <em>not</em> use the emphasis element
just because you like the look of italics.
</p>
Strong importance element
The strong importance element (<strong>
) should only be used for urgent or important information, such as a warning.
It should not be used just to make something bold.
<strong>
Warning! You can be fined up to £5,000 if you do not register.
</strong>
Idiomatic text element
It idiomatic text element (<i>
) should be used for text with a different semantic meaning to the surrounding text.
For example:
- an alternative voice or mood
- alternative languages or translations
- technical terms
- written thoughts
Image element
Images (<img>
) are for visual content. You must give them an alt text attribute. The alt text should describe the image or be left blank if the image is decorative.
<img src="cat.webp" alt="A tabby cat wearing sunglasses.">
<img src="background.webp" alt="">
Unordered list element
Use an unordered list when the reading order doesn’t matter.
<p>
To open a bank account, you need:
</p>
<ul>
<li>proof of address</li>
<li>a valid ID document</li>
<li>a minimum deposit of £1</li>
</ul>
Ordered list element
Use ordered lists where the order matters for context.
For example, a step-by-step process.
<p>Complete the following steps:</p>
<ol>
<li>Step 1: Go online</li>
<li>Step 2: Book your tickets</li>
<li>Step 3: Pick up your tickets when you arrive</li>
</ol>
Anchor element
An anchor element (<a>
), more commonly known as a hyperlink, is used to link the user to other parts of the page, other parts of the site, or other parts of the internet.
<a href="#main-content">Skip to main content</a>
<a href="/contact-us">Contact us</a>
<a href="https://gov.uk">GOV.UK</a>
Line break elements
Line breaks are used to force text onto a new line. They should not be used to create whitespace on a page.
Good example:
<p>
Mr Sherlock Holmes<br>
221B Baker Street,<br>
London<br>
NW1 6XE
</p>
Bad example:
<section id="section-1">…</section>
<br>
<br>
<br>
<br>
<section id="section-2">…</section>
Thematic break element
A thematic break element was historically called a horizontal rule. Which is why it uses the tag <hr>
.
You should avoid using these as they are not implemented consistently and if you structure your content properly, they are not needed.
If you need to create a visual horizontal rule, use CSS instead.
Heading element
Heading elements (<h1>
to <h6>
) need to be the marked up correctly, be the right level, and be easy to understand.
Marking up headings
You can’t just make the font look big and bold.
<h1>
This will behave like a heading
</h1>
<p class="large bold">
This may look like a heading, but it will not behave like one.
</p>
Heading levels
There are 6 levels. Realistically, if you need more than 3 or 4, your page is probably too complex!
<h1>Heading Level 1</h1>
<h2>Heading Level 2</h2>
<h3>Heading Level 3</h3>
<h4>Heading Level 4</h4>
<h5>Heading Level 5</h5>
<h6>Heading Level 6</h6>
Headings should be related
If you have a <h3>
and it does not relate to the <h2>
or <h1>
above it, then you’ve usually done something wrong.
<h1>COVID-19</h1>
<h2>How to stay safe</h2>
<h3>Wearing a mask</h3>
<h3>Washing your hands</h3>
<h3>Social distancing</h3>
<h2>How to get tested</h2>
<h3>Getting tested if you're a key worker</h3>
<h3>Getting a test for somebody in a care home</h3>
Don’t use the wrong heading level for stylistic purposes
<h1>
I want this text to be large
</h1>
<h5>
I want this text to be small
</h5>
If you need to make headings smaller, use CSS
<h1 class="heading-large">
I want this text to be large
</h1>
<h2 class="heading-small">
I want this text to be small
</h2>
.heading-large { font-size: 2rem; }
.heading-small { font-size: .5rem; }
Demo of heading-levels
Can be found at the following path:/demos/heading-levels
Language attribute
The language attribute (lang
) must be set on each page so that assistive technologies such as screen readers pronounce the words correctly.
It must also be set on any blocks which use a different language to the rest of the page.
Setting the language of the page
Using the lang
attribute on the HTML
element lets assistive technologies know the content on this page is written in English.
<!DOCTYPE html>
<html lang="en">
Language inheritance
Nested children inherit the same language as their parents. So, you don’t need to specify it on every element, just on the outer most container.
<html lang="en">
…
<body>
<p>
This paragraph inherits English from the body element,
and the body element inherits English from the HTML element.
</p>
</body>
</html>
Setting the language for a block
For anything that should not inherit from the page language, you need to add the lang attribute separately.
<html lang="en">
…
<body>
<h1>This heading is in English</h1>
<p>
This paragraph is also in English.
</p>
<p lang="fr">
Ce paragraphe est en Français
</p>
</body>
</html>
Two languages in the same block
You can mix multiple languages in a block by using an idiomatic text element (<i>
).
Don’t use a <span>
or it might not work. Remember, they are purely decorative.
<html lang="en">
<body>
<p>
Sometimes people mix languages in a paragraph,
but they don't apply the correct language attributes.
<i lang="fr">Ç'est la vie!</i>
</p>
</body>
</html>
Example of linking to Welsh
You may have a link on a service to translate it to Welsh.
<html lang="en">
<body>
<h1>Apply for a passport</h1>
<a href="/welsh" lang="cy">
Mae'r dudalen hon ar gael yn Gymraeg
</a>
…
</body>
</html>
Example of linking to English
On the Welsh language version, you would need to tag the English in the same way.
<html lang="cy">
<body>
<h1>Gwneud cais am basbort</h1>
<a href="/english" lang="en">
This page is available in English.
</a>
…
</body>
</html>
Demo of language attribute
Can be found at the following path:/demos/language-attributes
Page title element
Each page needs to have a unique and descriptive title so users can orientate themselves quickly and find content. It should tell them what page they’re on, and what website or service they’re on.
<title>
What is your name? - Apply for Universal Credit - GOV.UK
</title>
or
<title>
Tools and resources - DWP Accessibility Manual
</title>
Setting the page title
The title element is used inside the <head>
element on your page.
<!DOCTYPE html>
<html lang="en">
<head>
…
<title>Report a sighting of an excellent cow - GOV.UK</title>
</head>
…
</html>
Landmarks
Landmarks break the page down into defined areas, which helps people using assistive technology find content easier.
Landmark types
- Main
- Header
- Footer
- Navigation
- Form
- Aside
- Region
- Section
- Search
Basic page structure
Most basic pages are made up of:
- Header
- Page content
- Footer
Header
The header is usually consistent at the top of each page. It will usually contain a logo and maybe a navigation menu.
<header>
<img src="logo.webp" alt="Craig Abbott Logo">
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about-us">About us</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
Footer
Like the header, the footer is usually consistent at the bottom of each page. It usually contains useful links and copyright information.
<footer>
<h2>Support links</h2>
<ul>
<li><a href="/accessibility">Accessibility</a></li>
<li><a href="/cookies">Cookies</a></li>
<li><a href="/privacy">Privacy</a></li>
</ul>
<p>
© Craig Abbott. All rights reserved.
</p>
</footer>
The main landmark
The <main>
element is where you put the important stuff. There should only be 1 on each page.
A <h1>
should describe the content in it, and it should always have an ID to use a skip-link for bypass blocks.
<main id="main-content">
<h1>
A heading to describe the content
</h1>
<!-- The content -->
</main>
Demo of landmarks
Can be found at the following path:/demos/landmarks
Main skip-link
A skip-link should always be provided at the top of each page so that keyboard users can quickly get to the content they need.
<body>
<a href="#main-content">Skip to main content</a>
…
<main id="main-content">
…
</body>
Additional skip links
You might need additional skip links if you have other blocks of repeated content. Such as a social media feed in a sidebar.
<a href="#contact-details">Skip Twitter feed</a>
<div id="twitter-feed">
<a class="twitter-timeline" href="https://twitter.com/abbott567">
Tweets by @abbott567
</a>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<h2 id="contact-details">Contact details</h2>
But skip links look ugly!
They don’t need to be visible all the time. They can be hidden and only visible when they receive keyboard focus.
Not focused:
.skip-link {
position: absolute;
width: 1px;
height: 1px;
margin: 0;
overflow: hidden;
clip: rect(0 0 0 0);
}
Focused:
.skip-link:focus {
position: static;
width: auto;
height: auto;
margin: inherit;
overflow: visible;
clip: auto;
}
Demo of skip-link
Can be found at the following path:/demos/skip-link
Form elements
There are important elements such as <form>
, <button>
, <input>
and <label>
which are being covered in a separate session tomorrow.
Thank you!
Craig Abbott
Head of Accessibility, Digital
@abbott567