2.2.6 is upfront notice: users must be told the duration of any inactivity timeout that could cause data loss before they start, unless that data is preserved for more than 20 hours. It is distinct from 2.2.1 (Timing Adjustable), which governs extending or disabling the timer itself.
2.2.6 Timeouts
In Plain Language
2.2.6 Timeouts (Level AAA, added in WCAG 2.1) requires that users are warned of the duration of any user inactivity that could cause data loss, unless the data is preserved for more than 20 hours when the user does not take any action[1]. The warning has to be delivered upfront -- before the user starts the task -- not at the moment of expiry.
The failure mode is mechanistic: a multi-step application form silently expires at step 4 because the server killed the session at minute 15 of inactivity. The user walks back to the laptop, clicks a field, and the response is a redirect to a login screen with every entered value gone. 2.2.6 says the page had to state the inactivity window at step 1, or preserve the partial submission for more than 20 hours so the user could resume it.
Why It Matters
- Users with cognitive and learning disabilities often have no way to detect that an inactivity timer is running until their data is already discarded. An upfront duration disclosure is what lets them pace, take breaks, or ask for help before the timer fires[1].
- Screen-reader users and keyboard-only users traverse forms more slowly than a mouse user reading visually, so a 10- or 15-minute inactivity window that feels generous to a designer can expire mid-field. Knowing the exact duration is the input they need to decide whether to save a draft or break the task into chunks.
- Users of switch access, eye tracking, and voice control type at a small fraction of keyboard speed. Advance notice of the inactivity threshold is load-bearing for them: without it, the timer is an unannounced deadline they have no way to plan against.
- 2.2.6 pairs with 2.2.1 Timing Adjustable[2] and 2.2.5 Re-authenticating[3] but is not interchangeable with either. 2.2.1 governs the ability to extend or disable the timer, 2.2.5 governs data preservation across re-authentication, and 2.2.6 is the upfront disclosure that the timer exists and how long it is.
Examples
<form>...multi-step application form...</form>
✔ Users know the timeout duration before they start entering data
<!-- Warning displayed before the form -->
<div role="alert" class="timeout-warning">
<p>
⚠ This form will timeout after
15 minutes of inactivity. Your progress
will be saved as a draft.
</p>
</div>
<form id="application-form">
<!-- Form fields here -->
</form>
Server-side data retention policy:
sessionStorage.ttl = 24 hours
draftAutoSave.interval = 30 seconds
draftRetention = 7 days
✔ Data preserved for well over 20 hours -- no timeout warning required
<!-- Server configuration preserves data 7 days -->
<!-- No timeout warning needed per 2.2.6 -->
<script>
// Auto-save drafts every 30 seconds
setInterval(() => {
const formData = new FormData(
document.getElementById('app-form')
);
fetch('/api/save-draft', {
method: 'POST',
body: formData,
// Server retains drafts for 7 days
});
}, 30000);
</script>
Hidden timeout with no user-facing notice:
<meta http-equiv="refresh" content="600;url=/timeout">
<!-- 10-minute timeout, user never told -->
✘ Users discover the timeout only after losing their data
Warning appears only when time has already run out:
<div class="modal">
Your session has expired. All unsaved data is lost.
</div>
✘ The warning comes too late -- users needed to know the timeout duration before they started
How to Fix It
- Inventory every inactivity timeout that can destroy user data. Session cookies, CSRF tokens with short lifetimes, JWT expiry, auto-logout scripts, form state held only in client memory, and any back-end job that discards a partial submission all qualify. If the mechanism discards unsubmitted data when the user stops interacting, it is in scope for 2.2.6[1].
- State the exact inactivity duration before the task begins. Put a visible, programmatically-determinable notice at the start of the flow naming the threshold in concrete units -- "This form will time out after 15 minutes of inactivity" -- not a vague "sessions expire eventually". The notice has to reach the user before they commit effort, not at the moment of expiry.
- Or, preserve the data for more than 20 hours and skip the warning. Persisting partial form state to the back end (auto-saved drafts with a retention window beyond 20 hours) satisfies the exception clause in 2.2.6 and removes the need for an upfront duration notice[1]. This is the conformance path that produces the best user experience, because it eliminates the deadline rather than announcing it.
- Make the notice accessible by name, not by color. Render the warning as text inside the document flow so a screen reader encounters it in reading order. Do not rely on a yellow background or an icon alone -- 2.2.6 is about conveying the duration, and color is not readable to every user. A
role="alert"live region is appropriate when the notice appears after initial render; static notices do not need it. - Do not conflate 2.2.6 with 2.2.1. Offering a "extend session" button satisfies 2.2.1 Timing Adjustable[2] but does nothing for 2.2.6 on its own -- the button is only useful if the user knew the timer existed in time to press it.
References
- [1] W3C (2023). Understanding Success Criterion 2.2.6: Timeouts. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/timeouts.html ↩ ↩ ↩ ↩
- [2] 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 ↩ ↩
- [3] W3C (2023). Understanding Success Criterion 2.2.5: Re-authenticating. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/re-authenticating.html ↩