Module 4 · Web Development with JavaScript
HTML and accessibility
Write semantic HTML for the payment page (landmarks, headings, a proper table and a labelled form) so it works for everyone, including people using screen readers or keyboards, and check it.
About 15 minutes
The problem
Tallybook's old payment page was built from <div>s styled to look like a form. It looked fine. But a screen reader announced the amount box as just "edit text", the "Pay" button couldn't be reached with the keyboard, and the invoice table read out as a jumble of numbers. About 1 in 6 people live with some form of disability, and many more use phones in bright sun or with one hand.
Accessible HTML isn't extra work: it's using the right element for each job, which also makes pages easier to style, test and maintain.
The concept
Semantic elements
| Use | Instead of |
|---|---|
<header>, <main>, <nav>, <footer> | anonymous <div>s |
one <h1>, then <h2>, <h3> in order | bold text that looks like a heading |
<table> with <caption> and <th scope="col"> | a grid of <div>s for tabular data |
<button> | a clickable <div> (no keyboard, no role) |
<label for="amount"> linked to <input id="amount"> | placeholder text as the only label |
Forms
Every input needs a visible label. Give inputs the right type and inputmode (phones show a number pad for inputmode="decimal"), and connect hints and errors with aria-describedby.
Checking
Use the keyboard only (Tab, Shift+Tab, Enter, Space), zoom to 200%, and run the Lighthouse accessibility audit in Chrome's DevTools.
Example
The payment page's structure. Save it as pay.html and open it in your browser:
HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pay invoice INV-100832 · Tallybook</title>
</head>
<body>
<header>
<p>Tallybook · Ada Stores</p>
</header>
<main>
<h1>Pay invoice INV-100832</h1>
<table>
<caption>Invoice lines</caption>
<thead>
<tr><th scope="col">Item</th><th scope="col">Quantity</th><th scope="col">Price</th></tr>
</thead>
<tbody>
<tr><td>Bookkeeping, monthly</td><td>1</td><td>₦25,890.00</td></tr>
</tbody>
</table>
<h2>Balance</h2>
<p>Total ₦27,830.50 · paid ₦10,000.00 · <strong>due ₦17,830.50</strong></p>
<h2>Make a payment</h2>
<form id="payment-form">
<label for="amount">Amount in naira</label>
<input id="amount" name="amount" inputmode="decimal" autocomplete="off" aria-describedby="amount-hint" required>
<p id="amount-hint">Up to ₦17,830.50</p>
<label for="reference">Bank transfer reference</label>
<input id="reference" name="reference" aria-describedby="reference-hint" required>
<p id="reference-hint">From your bank's transfer confirmation</p>
<button type="submit">Record payment</button>
</form>
</main>
</body>
</html>Open it and press Tab: focus moves from the amount, to the reference, to the button, and Enter submits. Click the words "Amount in naira": the cursor jumps into the box, because the label is linked to the input. A screen reader would announce "Amount in naira, edit text, Up to ₦17,830.50". None of that needed any JavaScript or CSS.
Walkthrough
- Save and open the page. Navigate it with the keyboard only. Can you do everything?
- Remove the
for="amount"attribute and click the label again. What changed? - In Chrome DevTools, run Lighthouse with the Accessibility category. What score does it give, and what does it suggest?
- Fix an inaccessible form (the task below).
Practice
Task
5 minThis form is inaccessible: <div class="field">Email</div><input placeholder="Email"><div class="btn" onclick="send()">Send receipt</div>. Rewrite it as accessible HTML: a form, a label linked to an email input, and a real button.
Your work is checked for
- A form element
- A label with for=
- An input with a matching id
- type="email"
- A real button
- No clickable div
Check your understanding
Answer every question to check.