Modal Windows (INT-004)

Create keyboard friendly modal windows that trap focus

When modal windows are used they must be accessible for keyboard users. The modal must have a descriptive title that is read when launched, it must trap keyboard focus, focus order must follow the content from top to bottom and return to the top, and the ESC key must close the modal. When the modal is closed, focus should be returned to the triggering element.

Requirements

Modal role="dialog" (INT-WEB-004-01)

Modal windows MUST have the role attribute on the modal container set to role=“dialog” and the attribute aria-modal="true".

<div id="modal" role="dialog" aria-modal="true">
	<!-- Modal Content -->
</div>
		

Modals Have Titles (INT-WEB-004-02)

Modal windows MUST have aria-labelledby=“dialog-title” where dialog-title would be the modal’s title (e.g., main heading in modal).

<div id="modal" role="dialog" aria-labelledby="title">
	<h1 id="title">Payment Information</h1>
</div>
		

Modals Have Descriptions (INT-WEB-004-03)

Modal windows SHOULD have aria-describeby=“dialog-desc” where dialog-desc is some helpful information that is above the first focusable element.

<div id="modal" role="dialog" aria-labelledby="title" 
aria-describedby="description">
	<h1 id="title">Payment Information</h1>
	<div id="description" class="screen-reader-only">
		Use this modal window to pay for the thing you're trying to buy
	</div>
</div>
		

Modals Trap Focus (INT-WEB-004-04)

Modal windows MUST trap focus inside the modal.

<script src='scripts/jquery.min.js'></script>
<script src='scripts/jquery.trap.min.js'></script>

<div id="modal" role="dialog" aria-labelledby="title" 
aria-describedby="description">
	<h1 id="title">Payment Information</h1>
	<div id="description" class="screen-reader-only">
		Use this modal window to pay for the thing you're trying to buy
	</div>
</div>
		

$(document).ready(function(){
	$('#modal').trap();
)};
		

Modals Set Focus (INT-WEB-004-05)

Modal windows MUST have focus set to enable action without confusion. If the modal is primarily presenting text (including links) the focus SHOULD be placed on the heading or beginning of the text content to allow screen reader users to begin there. If the modal's goal is using interactive elements (i.e. form, button, etc.), focus SHOULD be placed on the first interactive element inside the modal, excluding any close button(s).

<div id="modal" role="dialog" aria-labelledby="title" 
aria-describedby="description">
	<h1 id="title">Payment Information</h1>
	<div id="description" class="screen-reader-only">
		Use this modal window to pay for the thing you're trying to buy
	</div>
	<label for="cardNum">Card Number</label>
	<input id="cardNum" type="number" />
</div>
		

$('button#openModal').click(function(){
	$('#modal').show()
		.find('input, select, textarea, a[href], button, [tabindex=0]')
		.first().focus();
});
		

Modals Wrap Around (INT-WEB-004-06)

Modal windows MUST allow the user to move through the modal's focusable elements, “wrapping around” from bottom-to-top and top-to-bottom using the < TAB > and < SHIFT >+< TAB > keyboard events.

<script src='scripts/jquery.min.js'></script>
<script src='scripts/jquery.trap.min.js'></script>

<div id="modal" role="dialog" aria-labelledby="title" 
aria-describedby="description">
	<h1 id="title">Payment Information</h1>
	<div id="description" class="screen-reader-only">
		Use this modal window to pay for the thing you're trying to buy
	</div>
</div>
		

$(document).ready(function(){
	$('#modal').trap();
)};
		

Modals Prevent Clicks Outside (INT-WEB-004-07)

Modal windows MUST prevent mouse-clicks that occur outside the modal from having any effect on the modal.

.modal-mask {
	position:fixed;
	top:0;
	left:0;
	width:100%;
	height:100%;
	background:rgba(0,0,0,0.8);
	z-index:999;
}
		

<div id="modal" role="dialog" aria-labelledby="title" 
aria-describedby="description">
	<h1 id="title">Payment Information</h1>
	<div id="description" class="screen-reader-only">
		Use this modal window to pay for the thing you're trying to buy
	</div>
</div>
<div id="mask" class"modal-mask" style="display:none;"></div>
		

$('button#openModal').click(function(){
	$('#mask').show();
	$('#modal').show()
		.find('input, select, textarea, a[href], button, [tabindex=0]')
		.first().focus();
});
		

Modals Trigger on Enter (INT-WEB-004-08)

Modal windows MUST have the < ENTER > keyboard event trigger set as the modal's main call-to-action (e.g. Submit form, etc.).

Modals Close on ESC (INT-WEB-004-09)

Modal windows MUST have the < ESC > keyboard event set to close the modal.

<div id="modal" role="dialog" aria-labelledby="title" 
aria-describedby="description">
	<h1 id="title">Payment Information</h1>
	<div id="description" class="screen-reader-only">
		Use this modal window to pay for the thing you're trying to buy
	</div>
</div>
		

$('#openModal').click(function(){
	$('#modal').show()
	$(document).on('keydown', function(evt){
		evt = evt || window.event;
		var charCode = evt.keyCode || evt.which;
		if(charCode === 27){
			$('#modal').hide();
		}
	});
});
		

Modals Restore Focus (INT-WEB-004-10)

Modal windows MUST restore focus to their triggering element when modal is closed.

<button class="open-modal" id="modalOpener">Open Modal</button>
		

var modelOpener = '';

$('.open-modal').click(function(){
	modalOpener = $(this).attr('id');
	$('#modal').show();
});

$('#closeModal').click(function(){
	$('#modal').hide();
	$('#' + modalOpener).focus();
});
		


Test Procedures

Screen reader (INT-WEB-004-01-T)

Confirm that when a modal window pops up, it is described to the user as such.

Screen reader (INT-WEB-004-02-T)

Confirm that when a modal window pops up, the modal's main heading or title is read aloud to the user.

Screen reader (INT-WEB-004-03-T)

Confirm that when a modal window pops up, any helpful information that is above the first focusable element is read aloud after the modal's main heading or title.

Screen reader (INT-WEB-004-04-T)

Confirm that focus is trapped inside all modal windows by cycling through headings, landmark roles, and links with each supported screen reader and confirming that focus stays within the modal and doesn't move the screen behind.

Keyboard (INT-WEB-004-05-T)

Confirm that when a modal window pops up, focus is set to the appropriate content. If the modal is primarily presenting text (including links), confirm that focus is placed on the heading or beginning of the text content. If the modal's goal is using interactive elements (i.e. form, button, etc.), confirm that focus is placed on the first interactive element inside the modal, excluding any close button(s).

Keyboard (INT-WEB-004-06-T)

Tab through the each modal window and confirm that the user can move through the modal's focusable elements, "wrapping around" from bottom-to-top and top-to-bottom using the < TAB > and < SHIFT >+< TAB > keyboard events.

Visual Inspection (INT-WEB-004-07-T)

Click outside the modal window with the mouse and confirm that it has no effect on the modal.

Keyboard (INT-WEB-004-08-T)

Hit < ENTER > in a modal and confirm that this keystroke trigger's the modal's main call-to-action (e.g., Submit form, etc.).

Keyboard (INT-WEB-004-09-T)

Hit < ESC > and confirm that the modal closes.

Keyboard (INT-WEB-004-10-T)

After hitting to close the modal, confirm that focus is restored to the triggering element on the page.


Related Content

WCAG Success Criteria

W3C Techniques

These materials and steps outlined on this website are provided “AS IS” and are intended for illustrative purposes only. They should not be relied upon for marketing, legal, tax, financial, regulatory or other advice. You are responsible for the legal aspects of any implementation of the concepts illustrated herein. Further, Visa neither makes any warranty or representation as to the completeness or accuracy of this information, nor assumes any liability or responsibility that may result from reliance on such information.  You should not act or rely on such content without seeking the advice of a professional.  All brand names, logos and/or trademarks are the property of their respective owners, are used for identification purposes only, and do not necessarily imply product endorsement or affiliation with Visa.