Who it affects
Someone using a screen reader to follow live football scores is thrown back to the top of the page every 30 seconds and never gets to the bottom half of the table.
Someone who reads slowly or uses magnification is still on the first paragraph when the page jumps away to the homepage.
Someone filling in the food bank's referral form loses everything they typed when a session timeout refresh fires.
Broken versus fixed
The broken markup is shown as code rather than rendered, because the effect is in how it is announced or handled, not how it looks.
<head>
<meta http-equiv="refresh" content="30">
<title>Live scores</title>
</head>
The whole page reloads every 30 seconds. Focus, scroll position and anything being read are lost.
<head>
<title>Live scores</title>
</head>
<body>
<button type="button">Refresh scores</button>
<table aria-live="polite">...</table>
</body>
The scores update when the person asks. For live updates, swap the data in place with script and let an aria-live region announce the change.
Test it by hand in two minutes
- View the page source (Ctrl+U) and search for http-equiv="refresh". Look at the number at the start of content; anything other than 0 is a delay.
- Open the page and leave it for two minutes without touching it. Did it reload or move?
- Watch the Network panel in DevTools for repeating page loads.
- If the page must update, confirm it does so without moving focus or scroll position, and that there is a way to pause it.
The fix
<meta http-equiv="refresh" content="30">
<button type="button">Refresh scores</button>
For live data, fetch new values with script and update the elements in place. For a moved page, use a server-side 301 redirect, or content="0;url=..." for an instant one.
Moved page
<meta http-equiv="refresh" content="5;url=/new-address">
<meta http-equiv="refresh" content="0;url=/new-address">
An instant redirect is allowed because there is nothing to interrupt. A server redirect is better again: no page flash, and search engines understand it.
Session timeout
<meta http-equiv="refresh" content="600;url=/logged-out">
<p role="alert">Your session ends in 2 minutes. <button type="button">Stay signed in</button></p>
Warn before a timeout and let the person extend it. WCAG 2.2.1 asks for at least 20 seconds' warning and a simple action to extend.
Common mistakes
- Changing the delay from 5 to 60 seconds; any delay under 20 hours still fails.
- Replacing the meta tag with setTimeout(location.reload), which does the same thing out of sight of the scanner.
- Using an instant meta redirect for every old URL instead of configuring the server.
- Refreshing the page to show a countdown or a clock.
WCAG criteria this rule maps to
axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:
- 2.2.1 Timing Adjustable (level A). Official W3C text.
The scanner finds meta http-equiv="refresh" elements and reads the delay; a value from 1 to 72000 seconds fails. It cannot see reloads or redirects done by JavaScript or by the server. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.
Related rules
marquee
The marquee element scrolls text across the page and never stops.
A
Do not use the blink element
blink
The blink element makes text flash on and off and gives nobody a way to stop it.
A
Sound must not start playing on its own
no-autoplay-audio
If a page starts playing sound by itself and keeps going for more than three seconds, it needs a way to stop or mute it before anything else on the page.
A
Every page needs a title
document-title
The title element in the head is the first thing a screen reader says when a page loads, the text on the browser tab, the name of the bookmark, and the headline in search results.