Level A

Session timeouts that fire without warning lock users out mid-task: screen-reader users, users with cognitive and learning disabilities, and users with motor disabilities all need more time to read, navigate, and complete forms than a fixed inactivity timer allows.

2.2.1 Timing Adjustable

In Plain Language

2.2.1 Timing Adjustable (Level A) governs every time limit the content itself sets -- session inactivity timers, auto-advancing carousels, countdowns on a form or quiz, a "complete checkout in 5 minutes" gate. For any such limit, at least one of the following must be true[1]:

  • Turn off: the user can disable the time limit before encountering it.
  • Adjust: the user can change the limit to at least ten times the default before encountering it.
  • Extend: the user is warned before the limit expires and given at least 20 seconds to extend it with a single-action input (pressing a key, clicking a button), with the option to extend at least ten times.

Three exceptions apply: real-time events where the limit is the function (live auctions, live betting, sports timing); essential time limits where extending would invalidate the activity (a proctored exam, a sealed-bid auction close); and limits that exceed 20 hours. 2.2.1 is distinct from 2.2.6 Timeouts (Level AAA, which requires warning users at the start of a process) and from 2.2.5 Re-authenticating (Level AAA, which governs recovering state after a session ends).

Why It Matters

  • Users with cognitive and learning disabilities need more time to read instructions, interpret form labels, and track multi-step flows. A five-minute inactivity timer fires mid-task and destroys their work.
  • Screen-reader users hear content linearly rather than scanning it. Navigating a complex form with heading and landmark jumps takes measurably longer than a sighted pass, and a fixed countdown penalizes that extra time.
  • Users with motor disabilities, switch users, and users of voice control operate input devices at rates the page author did not budget for. Strict time limits convert slow input into a hard failure.
  • Users with low vision who zoom, use screen magnification, or enlarge text re-read the same region multiple times to locate a field. An inactivity counter that resets only on mouse movement mistakes careful reading for idleness.
  • When a session expires without warning, all unsaved form state is lost. For a multi-step application -- unemployment benefits, health enrollment, government ID renewal -- that loss is the whole point of the barrier.

Examples

Do: Session timeout with extend option

Session timeout dialog:

Your session will expire in 2 minutes.

<button>Extend session</button> <button>Log out</button>

✔ Warning appears before timeout with an option to extend the session

<!-- Show warning dialog before session expires -->
<div role="alertdialog" aria-labelledby="timeout-title"
     aria-describedby="timeout-desc">
  <h2 id="timeout-title">Session expiring</h2>
  <p id="timeout-desc">
    Your session will expire in 2 minutes.
  </p>
  <button onclick="extendSession()">
    Extend session
  </button>
  <button onclick="logout()">Log out</button>
</div>
Do: Option to turn off auto-advance

Auto-advancing carousel with controls:

<button>Pause auto-advance</button>

Slide 2 of 5 -- auto-advances in 8 seconds

✔ User can pause or stop the automatic progression

<div role="region" aria-label="Featured content"
     aria-roledescription="carousel">
  <button aria-label="Pause auto-advance"
          onclick="toggleAutoAdvance()">
    Pause
  </button>
  <div aria-live="polite">
    Slide 2 of 5
  </div>
</div>
Don't: Silent session expiration

User is filling out a long form...

// Session expires after 5 minutes of inactivity

// No warning, no extend option

setTimeout(() => window.location = '/login', 300000);

✘ Session expires silently -- user loses all form data with no warning or extension option

Don't: Fixed countdown with no adjustment

Complete this survey within 3 minutes:

Time remaining: 2:47

// No option to extend, disable, or adjust the timer

✘ Fixed time limit with no way to turn off, adjust, or extend -- not an essential timed activity

How to Fix It

  1. Exempt the page if the limit is not essential. The cleanest fix is removing the limit. A session inactivity timer exists because of server-side state trade-offs, not because the activity requires timing -- if you can lengthen it to 20 hours or drop it, 2.2.1 no longer applies.
  2. Warn before timeout with role="alertdialog". Fire the warning at least 20 seconds before the limit expires so assistive technology has time to announce it and the user has time to respond. The dialog must receive focus and trap it until the user chooses Extend or Log out.
  3. Make Extend a single-action input. A button press, Enter key, or click -- not a captcha, not a re-auth flow, not a multi-step confirmation. The user must be able to extend the limit at least ten times from the same warning pattern[1].
  4. Preserve form state on timeout. If the session ends, the user's typed data should survive the re-auth round trip. Losing form state is not itself a 2.2.1 failure -- that is 2.2.5 territory -- but it is the impact users actually feel, and fixing it removes the sting from any timeout that does fire.
  5. Provide pause or stop controls on auto-advancing content. Carousels, slideshows, auto-refreshing news tickers, and rotating banners are content-imposed time limits. A visible Pause control that disables the advance satisfies the "turn off" branch for this class of timer (see also 2.2.2 Pause, Stop, Hide).
  6. Verify exception claims before relying on them. Real-time events, essential timing, and 20-hour-plus limits are the only carve-outs. A marketing countdown ("Offer expires in 2:47") is not a real-time event. A survey that could be retaken is not essential timing. If the exception does not apply, the three options above do.

References

  1. [1] W3C (2023). Understanding Success Criterion 2.2.1: Timing Adjustable. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/timing-adjustable.html