Skip to main content

Accessibility UI Guidelines: Modals

Modals

3.1 Modals

Modals are overlay elements that present content or require user interaction without navigating away from the current page. They are commonly used for dialogs, forms, alerts, and additional information. Ensuring that modals are accessible is vital for providing an inclusive experience for all users, including those using assistive technologies.

3.1.1 <dialog> Element

The HTML <dialog> element provides a native way to create modal dialogs. It offers built-in accessibility features and simplifies the implementation process.

<!-- Modal Trigger -->
<button id="openModal">Open Modal</button>

<!-- Modal Structure -->
<dialog id="myModal" aria-labelledby="modalTitle" aria-describedby="modalDescription">
    <h2 id="modalTitle">Modal Title</h2>
    <p id="modalDescription">This is an accessible modal dialog.</p>
    <button id="closeModal">Close</button>
</dialog>

3.1.2 Focus Management

Proper focus management ensures that keyboard users can interact with modals seamlessly.

// JavaScript to Manage Focus Within Modal
const openModalButton = document.getElementById('openModal');
const closeModalButton = document.getElementById('closeModal');
const modal = document.getElementById('myModal');
let lastFocusedElement;

openModalButton.addEventListener('click', () => {
    lastFocusedElement = document.activeElement;
    if (typeof modal.showModal === "function") {
        modal.showModal();
    } else {
        // Fallback for browsers that do not support <dialog>
        modal.style.display = 'block';
    }
    modal.setAttribute('aria-hidden', 'false');
    closeModalButton.focus();
    trapFocus(modal);
});

closeModalButton.addEventListener('click', () => {
    if (typeof modal.close === "function") {
        modal.close();
    } else {
        // Fallback for browsers that do not support <dialog>
        modal.style.display = 'none';
    }
    modal.setAttribute('aria-hidden', 'true');
    lastFocusedElement.focus();
});

function trapFocus(element) {
    const focusableElements = element.querySelectorAll('a[href], button, textarea, input, select, [tabindex]:not([tabindex="-1"])');
    const firstFocusable = focusableElements[0];
    const lastFocusable = focusableElements[focusableElements.length - 1];

    element.addEventListener('keydown', (e) => {
        const isTabPressed = (e.key === 'Tab' || e.keyCode === 9);
        if (!isTabPressed) return;

        if (e.shiftKey) { // Shift + Tab
            if (document.activeElement === firstFocusable) {
                e.preventDefault();
                lastFocusable.focus();
            }
        } else { // Tab
            if (document.activeElement === lastFocusable) {
                e.preventDefault();
                firstFocusable.focus();
            }
        }
    });
}

3.1.3 Keyboard Accessibility

Modals should be fully operable using the keyboard to accommodate users who rely on keyboard navigation.

<!-- Modal Structure with Close Button -->
<dialog id="myModal" aria-labelledby="modalTitle" aria-describedby="modalDescription">
    <h2 id="modalTitle">Modal Title</h2>
    <p id="modalDescription">This is an accessible modal dialog.</p>
    <button id="closeModal">Close</button>
</dialog>

// Listen for keydown events to handle Escape key
document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && modal.open) {
        modal.close();
        lastFocusedElement.focus();
    }
});

3.1.4 Visible Focus Indicators

Visible focus indicators help users identify which element is currently focused, especially during keyboard navigation.

/* Custom Focus Style for Modal Elements */
#myModal button:focus,
#myModal a:focus,
#myModal input:focus {
    outline: 2px solid #005fcc;
    background-color: #e0f0ff;
}

3.1.5 ARIA Attributes for Modals

Appropriate ARIA attributes enhance the accessibility of modals by providing additional context to assistive technologies.

<dialog id="myModal" role="dialog" aria-modal="true" aria-labelledby="modalTitle" aria-describedby="modalDescription">
    <h2 id="modalTitle">Modal Title</h2>
    <p id="modalDescription">This is an accessible modal dialog.</p>
    <button id="closeModal">Close</button>
</dialog>