Announcing changes, the last form attributes, and loading other people's code
How to tell a screen reader that something on the page just changed, the form attributes that only show up on real projects, how to load code from another site safely, and how the browser really reads your HTML.
By the end you can
- Tell a screen reader that part of the page has just changed
- Use the form attributes that only come up on real forms
- Load code from another site without handing over your page
- Explain what the browser does with markup you got slightly wrong
step 1 of 5
Telling people what just changed
Everything so far has been a page that sits still. The moment something on it changes by itself, a new problem appears.
Picture typing into a search box. Under it, a line quietly changes from '12 results' to '3 results'. You see it instantly. Someone listening to the page hears nothing at all, because the screen reader has already moved on. They have no idea anything happened.
The fix is to mark that line as a place worth watching: aria-live="polite". The screen reader then reads out the new words, waiting until it has finished whatever it was saying.
There is also aria-live="assertive", which interrupts immediately. Save it for something that truly cannot wait, like a session about to expire. Using it for a small "Saved" message is like shouting across a room to say the kettle has boiled.
One catch that surprises everybody. The watched element has to already be on the page, even while it is empty. If you create the element and its message at the same moment, there was nothing to watch, so nothing is announced.
Two more. aria-describedby points a box at the id of text that explains it: a hint under a field, or an error message. The explanation is then read out after the label.
aria-expanded says whether the thing a button controls is open or shut, and aria-controls names it by id. Without them, a menu button is silent about its own state.
Wire up the three on the right.
<p id="count" aria-live="polite"></p>
<label for="phone">Phone</label>
<input id="phone" name="phone" aria-describedby="phone-help" />
<p id="phone-help">We only call about this order.</p>
<button type="button" aria-expanded="false" aria-controls="filters">Filters</button>
<div id="filters" hidden>...</div>What these words mean
- live region
- A part of the page a screen reader watches, so changes inside it are read out.
- aria-live="polite"
- Read the change out when there is a pause. The right default.
- aria-live="assertive"
- Interrupt and read it now. For emergencies only.
- role="status"
- A live region with polite built in. role="alert" is the assertive version.
- aria-describedby
- The id of text that explains this box. Read out after the label.
- aria-expanded
- Whether the thing this button controls is open. Your code must keep it correct.
- aria-controls
- The id of the element this button operates.
- inert
- Switches off a whole part of the page: no clicking, no keyboard, nothing read out.
Easy to get wrong
Creating the live region and its message together
Leave the empty region on the page, then fill it
A screen reader announces changes inside something it was already watching. Add both at once and there was nothing being watched, so the message is silent.
aria-expanded that never changes
Your code flips it to true when the menu opens
A permanent false tells everybody the menu is shut while it stands open in front of them. A wrong answer is worse than no answer.
What we check
- The results count is a polite live region
- The search box points at its help text
- That description actually exists on the page
- The toggle states whether it is open, and what it controls
- aria-controls names a real element
- Nothing interrupts the listener unnecessarily
Next