no-visible-close-modal-button
Web validation
A visible close button gives all users a clear, predictable way to leave a modal dialog. Without it, users must guess how to close the modal, for example by pressing Escape or clicking outside it. Many users don't know these shortcuts, and some of them don't work with every input method. The most common approach is to place a button with a cross icon at the top right of the modal, or at the top left for right-to-left languages. A text button such as "Cancel" or "Close" at the bottom of the modal also works.
The close button should:
- Be a real button, a
<button>element or an element withrole="button", so it is included in the tab sequence and can be activated with the keyboard. - Stay visible while the modal is open, not only on hover.
- Have an accessible name, such as
aria-label="Close", when it shows only an icon.
Pass Patterns
Close icon button
The modal has a visible <button> with a cross icon at the top, and aria-label gives the icon button its name.
<div role="dialog" aria-modal="true" aria-labelledby="settings-title">
<button class="close-button" aria-label="Close">
<svg aria-hidden="true" focusable="false"><!-- cross icon --></svg>
</button>
<h2 id="settings-title">Settings</h2>
<p>Choose your notification preferences.</p>
</div>Cancel button
The modal has a visible text button that closes it.
<dialog id="delete-dialog" aria-labelledby="delete-title">
<h2 id="delete-title">Delete file?</h2>
<button id="cancel-delete">Cancel</button>
<button id="confirm-delete">Delete</button>
</dialog>Fail Patterns
No close button
The modal closes only when the user presses Escape or clicks outside it. There is no visible button to close it.
<div role="dialog" aria-modal="true" aria-labelledby="promo-title">
<h2 id="promo-title">Summer sale</h2>
<p>Get 20% off all items this week.</p>
</div>Close icon that is not a button
The cross icon is a plain <span> with a click handler. It is visible, but it has no button role and is not in the tab sequence, so keyboard users cannot reach it.
<div role="dialog" aria-modal="true" aria-labelledby="promo-title">
<span class="close-icon" onclick="closeModal()">×</span>
<h2 id="promo-title">Summer sale</h2>
<p>Get 20% off all items this week.</p>
</div>Try It Yourself
Using a keyboard
- Use the Tab key to move to the control that opens the modal, and press Enter or Space to open it.
- Press Tab and Shift+Tab to move through the elements inside the modal.
- Look for a visible close or cancel button, and check that it receives focus.
- Press Enter or Space on it.
Expected results: The modal has a visible close or cancel button that receives focus and closes the modal when activated.
Actual results: The modal has no visible close button, or the close icon cannot be reached or activated with the keyboard.
Using a screen reader
New to screen reader testing, or need a refresher?
Review this article first: Practical guides for using screen readers
- Load the page, open a screen reader, and open the modal.
- Move through the elements inside the modal.
Expected results: The screen reader announces a button with a clear name, such as “Close, button” or “Cancel, button”.
Actual results: No close button is announced, or the close icon is announced without a button role or a name.
FAQ
Why is this validation considered a best practice?
WCAG does not require a visible close button. It requires that keyboard users can leave the modal, which other methods, such as the Escape key, can satisfy. However, a visible close button is the clearest and most predictable way to close a modal, and it works for every user and input method.
Why is this issue marked as Moderate?
Users can often still close the modal with Escape or by clicking outside it, so they are not always blocked. However, many users don't know these methods, and without a visible button they may struggle to return to the page content, so it is rated moderate.
What if there is no way to close the modal with the keyboard?
Then the modal also has a more serious problem. If keyboard users cannot reach a close button and Escape does not work, they may be unable to leave the modal at all, which can fail WCAG 2.1.2 No Keyboard Trap. Review the related focus-trap and modal-dismissed-on-esc validations.