ADA Compliance Professionals

    Do not use the meta refresh tag

    Last updated:

    Who it helps:
    Cognitive
    Standard:
    WCAG 2.2 Level A

    Do not use meta refresh for redirects or timed reloads

    Pages must not use the meta http-equiv="refresh" tag. Automatic page reloads or delayed redirects remove user control and can reset focus to the top of the document. This affects keyboard users, screen reader users, and anyone who needs more time to read or interact.

    Why It Matters

    Auto-refresh and delayed redirects can disorient users and cause loss of context. Screen reader users may be returned to the start of the page with no clear indication of what changed. Keyboard users can lose their place in the tab order and must start over.

    Timed actions without user control can also harm users with cognitive disabilities who need more time to read, as well as people on slower networks who are mid-task when the refresh interrupts them. From a technical standpoint, server-side redirects are also more reliable than client-side meta refresh.

    Common Causes

    • Copying an old HTML snippet that adds a timed redirect.
    • Using meta refresh to auto-log out or auto-rotate content.
    • Attempting to reload dashboards or feeds without scripting.
    • Implementing temporary redirects on static hosting via HTML only.
    • Assuming meta refresh is needed for SEO or caching (it is not).

    How to Fix

    1. Remove the meta refresh tag
      • Delete any <meta http-equiv="refresh" ...> from the page head.
    2. Use proper redirects
      • For routing, configure server-side redirects (HTTP 301/302) or your CDN/host rules. This avoids a client-side page reload and preserves accessibility.
    3. For live data, update content without reloading
      • Use JavaScript to fetch and replace only the changing region.
      • Default auto-updates to off. Provide controls to start, pause, change the interval, and update on demand.
      • Announce updates with a polite live region. Do not move keyboard focus.
    4. Provide timing control if auto-updates are essential (WCAG 2.2.1)
      • Allow users to turn off auto-update, adjust the interval, or extend time at least 10x the default.
      • If a forced time limit is necessary, warn users and provide at least 20 seconds to extend the timer with a simple action.
    5. Preserve focus and position
      • Avoid full page reloads. Keep the user’s scroll position and focus on their current control.

    Recommendation: If you must refresh data periodically, default to manual refresh with a clear button and optional, user-initiated auto-update.

    How to Test

    • Code review
    • Search the HTML for <meta http-equiv="refresh">. None should exist.
    • Keyboard check
    • Interact with the page for several minutes. Focus must not jump to the top without your action.
    • If auto-update exists, you can start, pause, and change the interval using only the keyboard.
    • Screen reader check (NVDA/JAWS/VoiceOver)
    • Confirm the page does not reload unexpectedly.
    • For live updates, ensure changes are announced via a polite region and focus does not move.
    • Mobile/touch check
    • No unrequested reloads. Controls are operable by touch, and timing can be paused or adjusted.
    • Redirect behavior
    • If a redirect is required, verify it occurs via HTTP 301/302 at the network level, not by client-side refresh.

    Good Example

    A feed that a user can update manually or start/pause auto-updates. No page reloads; updates are announced politely.

    HTML
    <label for="interval">Update every (seconds):</label>
    <input id="interval" type="number" min="10" value="60">
    <button id="start">Start updates</button>
    <button id="pause">Pause updates</button>
    <button id="refresh">Update now</button>
    <p id="status" role="status" aria-live="polite">Auto-updates off.</p>
    <section id="news" aria-live="polite"></section>
    <script>
    let timer = null;
    const intervalInput = document.getElementById('interval');
    const status = document.getElementById('status');
    const region = document.getElementById('news');
    
    function loadItems() {
      region.setAttribute('aria-busy', 'true');
      fetch('/api/news')
        .then(r => r.json())
        .then(items => {
          region.innerHTML = items.map(i => `<p>${i.title}</p>`).join('');
          status.textContent = 'Content updated.';
        })
        .catch(() => { status.textContent = 'Update failed.'; })
        .finally(() => region.removeAttribute('aria-busy'));
    }
    
    document.getElementById('start').addEventListener('click', () => {
      const seconds = Math.max(10, Number(intervalInput.value) || 60);
      if (timer) clearInterval(timer);
      timer = setInterval(loadItems, seconds * 1000);
      status.textContent = `Auto-updates every ${seconds}s.`;
    });
    
    document.getElementById('pause').addEventListener('click', () => {
      clearInterval(timer);
      timer = null;
      status.textContent = 'Auto-updates paused.';
    });
    
    document.getElementById('refresh').addEventListener('click', loadItems);
    </script>

    Bad Example

    A page that reloads itself or redirects after a delay using meta refresh.

    HTML
    <meta http-equiv="refresh" content="30">
    <!-- or a timed redirect -->
    <meta http-equiv="refresh" content="5;url=/new-location">

    Quick Checklist

    • No <meta http-equiv="refresh"> tags anywhere.
    • Redirects happen via HTTP 301/302, not client-side refresh.
    • Auto-updates are optional, user-initiated, and easy to pause/adjust.
    • Users can extend or turn off timed actions (meets WCAG 2.2.1 intent).
    • Live updates do not move focus; changes are announced politely.
    • Page does not reload unexpectedly; focus and scroll position are preserved.
    • All controls work with keyboard and touch, and are clearly labeled.