WCAG 2.2.6: Timeouts

Understanding WCAG 2.2.6: Timeouts

The WCAG 2.2.6 Timeouts success criterion, classified under Guideline 2.2: Enough Time, addresses a critical aspect of user experience and accessibility: session management. It mandates that if user inactivity on a web page or application could lead to data loss, users must be informed about the impending timeout and be given a reasonable opportunity to extend their session.

This criterion is crucial for maintaining user trust and preventing frustration, especially in scenarios where users are inputting significant amounts of data, completing complex forms, or engaging with systems that require focused attention over time.

Why WCAG 2.2.6 Timeouts Matters for Accessibility

Session timeouts, when not handled gracefully, can pose significant barriers for various user groups and negatively impact their ability to complete tasks effectively. Adhering to this criterion helps to:

  • Prevent Data Loss and Frustration: Imagine filling out a long form, only for the session to expire and all your progress to be lost. This is incredibly frustrating and discourages users from attempting the task again.
  • Support Users with Cognitive Disabilities: Individuals with cognitive, learning, or neurological disabilities may require more time to process information, make decisions, or complete tasks. Unexpected timeouts can disrupt their thought processes and make complex interactions impossible.
  • Assist Users with Motor Impairments: Users relying on assistive technologies like switch controls, voice input, or specialized keyboards may take longer to navigate and interact with interfaces. Short or unannounced timeouts can prematurely end their session before they’ve had a chance to complete their input.
  • Aid Screen Reader Users: Screen reader users often navigate sequentially and may need extra time to understand the context of a page or form fields. An abrupt timeout can leave them disoriented and lose their place.
  • Accommodate Users with Low Vision: Users with low vision who rely on magnifiers might take longer to locate elements, read text, or identify areas for interaction.
  • Account for Distractions and Interruptions: Any user can be interrupted by real-world events (e.g., a phone call, a child needing attention). A well-implemented timeout warning allows them to pause, handle the interruption, and then easily resume their task without data loss.

WCAG 2.2.6 Success Criterion Explained

The core requirement of Success Criterion 2.2.6 is straightforward:

If a non-essential timeout occurs on the page, the user is warned and given at least 20 seconds to extend the timeout with a simple action (e.g. a single key press or tap).

Let’s break down the key components:

  • “Non-essential timeout”: This applies to timeouts that are not critical for security or where the data is not real-time. For example, a banking transaction might have an “essential” timeout for security, while filling out a contact form is “non-essential.”
  • “If a non-essential timeout occurs on the page”: This implies that the criterion is triggered when the system automatically logs out a user or clears their input due to inactivity.
  • “The user is warned”: A clear, understandable notification must be provided. This warning should be accessible to all users, including those using assistive technologies.
  • “Given at least 20 seconds to extend the timeout”: The warning must appear with enough time for the user to react. 20 seconds is the minimum, but longer is often better.
  • “With a simple action (e.g. a single key press or tap)”: Extending the session should be easy and quick. A prominent button, a checkbox, or even an automatic extension upon interaction are good examples.

Exceptions to this Criterion:

There are specific scenarios where this criterion does not apply:

  • Real-time Exception: When the timeout is part of a real-time event where the user must act within a specific timeframe, and extending the timeout would invalidate the activity. Examples include online auctions or live quizzes.
  • Essential for Security: When the timeout is absolutely essential for the security of the content and data, and extending it would compromise security. This is often seen in high-security applications like banking or government portals where an automatic logout after a short period is a security measure. However, even in these cases, if data loss is involved, the application should strive to save progress where possible or provide a less disruptive experience.

Practical Guidelines for Compliance

To implement WCAG 2.2.6 effectively, consider the following practical steps:

1. Identify Data-Loss Scenarios

  • Review all parts of your application where users might input data (forms, rich text editors, wizards, shopping carts) or where their session state is critical (e.g., an authenticated dashboard).
  • Determine if inactivity would result in the loss of unsaved changes or critical session data.

2. Design a Clear and Accessible Warning Mechanism

  • Prominence: The warning must be highly visible and stand out from the page content. Use contrasting colors, larger text, or a modal dialog.
  • Location: Place the warning in a consistent and predictable location, usually at the top of the viewport or as a central modal.
  • Timing: Trigger the warning significantly before the actual timeout. WCAG specifies “at least 20 seconds,” but for complex tasks, more time (e.g., 60-120 seconds) is recommended.
  • Content: Clearly state that the session is about to expire, how much time is left, and what will happen if it expires (e.g., “Your session will expire in X seconds, and any unsaved changes will be lost”).
  • Accessibility: Ensure the warning is programmatically discernible.
    • For screen reader users, the warning should immediately announce itself (e.g., using aria-live="assertive" on the container).
    • The focus should ideally move to the warning message or the “Extend Session” button when it appears.

3. Provide an Easy Option to Extend

  • Clear Call-to-Action: Offer a prominent button or link like “Extend Session,” “Keep me logged in,” or “Continue.”
  • Simple Interaction: The action should require minimal effort, such as a single click, tap, or key press. Avoid complex multi-step processes.
  • Feedback: Once the user extends the session, provide clear feedback that the session has been extended and the timeout has been reset. The warning should then disappear.
  • Automatic Extension (Optional but Recommended): For some applications, any user interaction (e.g., typing, clicking, scrolling) could automatically reset the timer without an explicit “extend” button, as long as the initial warning is still provided.

4. Handle the Timeout Gracefully if Not Extended

  • If the user does not extend the session, ensure that data loss is minimized where possible. Can draft data be saved locally or to the server temporarily?
  • Clearly communicate that the session has expired and guide the user on what to do next (e.g., “Your session has expired. Please log in again to continue.”).

Examples of Implementations

Correct Implementations

Example 1: Modal Dialog with Warning and Extend Button

A common and effective approach is to use a modal dialog that appears centrally, drawing immediate attention. The dialog provides a countdown and a clear button to extend the session.

HTML Structure:

<div id="session-timeout-modal" role="dialog" aria-modal="true" aria-labelledby="timeout-title" style="display:none;">
    <h2 id="timeout-title">Session Expiration Warning</h2>
    <p>Your session will expire in <span id="countdown">60</span> seconds. Any unsaved data will be lost.</p>
    <p>Please click 'Extend Session' to continue working.</p>
    <button id="extend-session-btn">Extend Session</button>
</div>
<div class="overlay" style="display:none;"></div>

CSS for Modal and Overlay:

#session-timeout-modal {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: white;
    padding: 30px;
    border: 1px solid #ccc;
    box-shadow: 0 0 10px rgba(0,0,0,0.5);
    z-index: 1000;
    text-align: center;
    width: 300px;
    border-radius: 8px;
}
.overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.6);
    z-index: 999;
}
#extend-session-btn {
    background-color: #007bff;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 1em;
    margin-top: 15px;
}
#extend-session-btn:hover {
    background-color: #0056b3;
}

JavaScript Logic:

let timeoutInSeconds = 300; // 5 minutes session
let warningThreshold = 60; // Warn 60 seconds before timeout
let timeoutTimer;
let countdownTimer;

function startSessionTimer() {
    clearTimeout(timeoutTimer);
    clearTimeout(countdownTimer);
    timeoutTimer = setTimeout(showTimeoutWarning, (timeoutInSeconds - warningThreshold) * 1000);
    console.log("Session timer started. Warning in " + (timeoutInSeconds - warningThreshold) + " seconds.");
}

function showTimeoutWarning() {
    const modal = document.getElementById('session-timeout-modal');
    const overlay = document.querySelector('.overlay');
    const countdownSpan = document.getElementById('countdown');
    const extendBtn = document.getElementById('extend-session-btn');

    modal.style.display = 'block';
    overlay.style.display = 'block';
    countdownSpan.textContent = warningThreshold; // Initialize countdown

    // Announce the modal to screen readers
    modal.setAttribute('aria-live', 'assertive');
    modal.setAttribute('tabindex', '-1'); // Make modal focusable
    modal.focus(); // Move focus to the modal

    let remainingTime = warningThreshold;
    countdownTimer = setInterval(() => {
        remainingTime--;
        countdownSpan.textContent = remainingTime;
        if (remainingTime <= 0) {
            clearInterval(countdownTimer);
            handleSessionTimeout(); // Actual timeout
        }
    }, 1000);

    extendBtn.onclick = extendSession;
    console.log("Timeout warning shown.");
}

function extendSession() {
    const modal = document.getElementById('session-timeout-modal');
    const overlay = document.querySelector('.overlay');

    modal.style.display = 'none';
    overlay.style.display = 'none';
    clearInterval(countdownTimer);
    modal.removeAttribute('aria-live'); // Remove assertive role after hiding

    // Make an AJAX call to the server to extend the session
    // For demonstration, we'll just reset the client-side timer
    console.log("Session extended!");
    startSessionTimer(); // Restart the main session timer
}

function handleSessionTimeout() {
    console.log("Session timed out!");
    alert("Your session has expired due to inactivity. You will be logged out.");
    // Redirect to login page or clear user data
    // window.location.href = '/logout';
}

// Start the timer when the page loads or after user activity
document.addEventListener('DOMContentLoaded', startSessionTimer);
document.addEventListener('mousemove', startSessionTimer); // Reset on activity
document.addEventListener('keydown', startSessionTimer);   // Reset on activity

Example 2: Top Banner Notification with Auto-Extend

A less intrusive, but still effective, method is a banner notification that appears at the top of the page. It can be combined with auto-extension on user activity for a smoother experience.

HTML Structure:

<div id="timeout-banner" role="alert" aria-live="polite" style="display:none;">
    <p>Your session will expire in <span id="banner-countdown">60</span> seconds. <button id="banner-extend-btn">Extend Now</button></p>
</div>

CSS for Banner:

#timeout-banner {
    background-color: #ffc107; /* Warning yellow */
    color: #333;
    padding: 10px;
    text-align: center;
    position: sticky; /* Or fixed for always visible */
    top: 0;
    width: 100%;
    z-index: 990;
    border-bottom: 2px solid #e0a800;
}
#banner-extend-btn {
    background-color: #28a745; /* Green for "Extend Now" */
    color: white;
    padding: 5px 15px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    margin-left: 10px;
}
#banner-extend-btn:hover {
    background-color: #218838;
}

JavaScript Logic (modified from previous):

let bannerTimeoutInSeconds = 300; // 5 minutes session
let bannerWarningThreshold = 60; // Warn 60 seconds before timeout
let bannerTimeoutTimer;
let bannerCountdownTimer;

function startBannerSessionTimer() {
    clearTimeout(bannerTimeoutTimer);
    clearTimeout(bannerCountdownTimer);
    bannerTimeoutTimer = setTimeout(showBannerTimeoutWarning, (bannerTimeoutInSeconds - bannerWarningThreshold) * 1000);
}

function showBannerTimeoutWarning() {
    const banner = document.getElementById('timeout-banner');
    const countdownSpan = document.getElementById('banner-countdown');
    const extendBtn = document.getElementById('banner-extend-btn');

    banner.style.display = 'block';
    countdownSpan.textContent = bannerWarningThreshold; // Initialize countdown

    let remainingTime = bannerWarningThreshold;
    bannerCountdownTimer = setInterval(() => {
        remainingTime--;
        countdownSpan.textContent = remainingTime;
        if (remainingTime <= 0) {
            clearInterval(bannerCountdownTimer);
            handleBannerSessionTimeout(); // Actual timeout
        }
    }, 1000);

    extendBtn.onclick = extendBannerSession;
    console.log("Banner timeout warning shown.");
}

function extendBannerSession() {
    const banner = document.getElementById('timeout-banner');
    banner.style.display = 'none';
    clearInterval(bannerCountdownTimer);
    console.log("Session extended from banner!");
    startBannerSessionTimer(); // Restart the main session timer
}

function handleBannerSessionTimeout() {
    console.log("Banner session timed out!");
    alert("Your session has expired due to inactivity. You will be logged out.");
    // Redirect or perform logout actions
}

// Reset timer on any activity for "auto-extend" behavior
document.addEventListener('DOMContentLoaded', startBannerSessionTimer);
document.addEventListener('mousemove', () => {
    if (document.getElementById('timeout-banner').style.display === 'none') { // Only reset if warning not active
        startBannerSessionTimer();
    }
});
document.addEventListener('keydown', () => {
    if (document.getElementById('timeout-banner').style.display === 'none') {
        startBannerSessionTimer();
    }
});

Incorrect Implementations

Example 1: Abrupt Session Expiration Without Warning

The most common incorrect implementation is when a session simply expires, often redirecting the user to a login page, without any prior warning or opportunity to extend.

JavaScript (Simulated):

let sessionTimeout = 300; // 5 minutes
setTimeout(() => {
    console.log("Session expired!");
    // window.location.href = '/login?sessionExpired=true'; // Redirects user
    alert("Your session has expired due to inactivity."); // Data lost if not saved
}, sessionTimeout * 1000);

Why it's incorrect: The user receives no warning that their session is about to expire, leading to potential data loss and a frustrating user experience, especially for those who need more time.

Example 2: Warning Without an Option to Extend

Another incorrect approach is providing a warning, but not giving the user an option to extend the session, or making the extension process overly complicated.

HTML (Simulated):

<div id="bad-timeout-warning" style="display:none;">
    <p>Warning: Your session will expire in <span id="bad-countdown">30</span> seconds.</p>
    <!-- No button or clear instruction to extend -->
</div>

JavaScript (Simulated):

// Assume a timer triggers a similar warning, but with no 'extend' button
// ... then it just times out.
// Or, imagine a warning that says "Please re-login to extend" - this isn't a simple action.

Why it's incorrect: While a warning is present, the lack of a simple, direct way to extend the session violates the criterion's requirement to provide an "option to extend it with a simple action." Users are still forced to lose their progress and restart.

Best Practices and Common Pitfalls

Best Practices

  • Provide Ample Time: While 20 seconds is the minimum, consider offering 60-120 seconds or more for complex tasks to give users sufficient time to react.
  • Make Warnings Obvious: Use prominent visual cues (modal, banner, contrasting colors, large text) and ensure they are announced by screen readers (aria-live="assertive").
  • Ensure Operability: The "Extend Session" action must be easy to find and operate with various input methods (mouse, keyboard, touch, voice).
  • Progressive Enhancement: Implement timeout handling in a way that works even if JavaScript fails or is disabled (e.g., server-side session management with graceful degradation).
  • Test with Assistive Technologies: Verify that the warning and extension mechanism are fully accessible when using screen readers, keyboard navigation, and other assistive devices.
  • Consider Auto-Save: Where possible, implement auto-save functionality for long forms or content creation areas to minimize data loss, even if a session expires unexpectedly.
  • Clear Language: Use straightforward and unambiguous language in your warning messages. Avoid jargon.

Common Pitfalls

  • Invisible or Obscure Warnings: Warnings that are too subtle, blend into the background, or are placed in an easily missed area.
  • Insufficient Warning Time: Providing only a few seconds before actual timeout, which is not enough for many users to react.
  • Missing or Unclear Extend Options: Failing to provide an option to extend the session, or burying it in a complex menu.
  • Warnings that Disappear Too Quickly: A warning message that vanishes before the user has a chance to read and react.
  • Not Considering All Data Loss Scenarios: Only implementing timeout warnings for login sessions but forgetting about unsaved form data on public pages or within specific features.
  • Relying Solely on Visual Cues: Designing warnings that are only conveyed visually, making them inaccessible to users who cannot see the screen.
  • Over-Application of Exceptions: Misinterpreting "essential for security" or "real-time" exceptions to avoid implementing the criterion where it truly applies.

Conclusion

WCAG 2.2.6 Timeouts is a vital criterion for fostering an inclusive and user-friendly web. By thoughtfully implementing session timeout warnings and providing easy ways to extend sessions, you prevent data loss, reduce user frustration, and ensure that individuals with diverse needs have sufficient time to complete their tasks without unnecessary barriers. Adhering to this guideline is not just about compliance; it's about respecting your users' time and effort.

Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.