• Organism
  • CORE COMPONENT
  • Taxonomic name: O-MODAL
  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.11.0 (07/09/21)

Modal

Modal windows can be used when it is appropriate to interrupt a task performed on a page, for example when an important action needs to be completed. However, they can cause serious usability issues and introduce unnecessary pain points and so should generally be discouraged. Consider whether housing the content within the same page, navigating to a new page, or another mechanism would be more appropriate.


Design and usage

Structure

  • Modals always have a heading.
  • Modals may only contain one primary call to action (if needed) and up to 2 other buttons (secondary or tertiary).
  • Modals by default should have a header close button. The close button should only be hidden in cases where the user is required to make a choice before proceeding.
  • OPTIONAL: Modals can include a secondary CTA at the bottom to close the modal; the label is customisable.
  • If the header close button is present, pressing the escape key will close the modal. If not, the escape key does nothing
  • If the header close button is present, modals should by default close when the user clicks/taps outside of them (desktop and tablet). If not, the modal stays open.

Placement

  • CTAs that trigger a modal can be placed anywhere on a page.
  • Desktop/tablet – A modal appears in the centre of the viewport.
  • Mobile – A modal covers the whole page and the top-right close button sticks to the top of the screen when a user scrolls.

Labels

  • Button labels are customisable.
  • When a header close button is present, its label should always be 'Close' (or its local language equivalent).

Non-JavaScript

  • CTA for the modal window becomes an anchor link and the modal content is shown within the main page.
  • Content is always shown before the global navigation and footer; projects can define where the content should appear (for example as the last section before the global navigation and footer).

Use case

  • Modal windows can be used within process flows to provide additional detailed information or to avoid having to send a user on a secondary journey.
  • Content inside a modal can be sub-sections loaded from other pages, for example a specific T&Cs section.
  • Do not use for promotional / non-critical content, unless part of a process user journey like quote and buy.
  • Do not use to hide content that is critical to making an informed decision to buy a product.
  • Do not use to hide critical information that is part of a process user journey eg. how we use your email address during a change email journey.
  • Do not use to hide legal or regulatory content.
  • Do not use form fields inside modals - use fullscreen modals instead.

Examples

Interactive example

Code example

Linking to modal content

<!-- Standard modal link -->
<a href="..." data-module="o-modal" data-module-load="true">
	...
</a><!-- Disable close outside -->
<a href="..." data-module="o-modal" data-module-load="true" data-modal-disable-close="true">
	...
</a><!-- Disable close header link and close outside -->
<a href="..." data-module="o-modal" data-module-load="true" data-modal-disable-close="all">
	...
</a>

Modal content - within same page

<div id="..." class="o-modal__content-container">
	...
</div>

Demonstration of extended functionality

<script>
document.addEventListener( 'frameworkready', function () {
	FRAMEWORK.require([ utility ], function ( utility ) {
		// Wrapping functionaility to run this once elements are on the page		document.querySelector( '.close-test' ).addEventListener( 'click', function listener( event ) {
			event.preventDefault();
			setTimeout( function () {
				utility.trigger( window, 'modal:close' );
				document.querySelector( '.notification-target' ).innerHTML = '';
			}, 1000 );
		});
		document.querySelector( '.destroy-test' ).addEventListener( 'click', function listener( event ) {
			event.preventDefault();
			setTimeout( function () {
				utility.trigger( window, 'modal:destroy' );
				document.querySelector( '.notification-target' ).innerHTML = '<div class="m-card m-card-notification m-card-notification--success" role="status"><div class="m-card-content"><div class="m-card-content__inner"><p>Function successful</p></div></div></div>';
			}, 1000 );
		});		// Closing wrapping functionality
	});
});
</script>
<a href="..." data-module="o-modal">
	...
</a>
<div class="notification-target"></div>
<div class="o-modal-target"></div>

Development and test

Notes for developers

Content can only be loaded in to a modal either from within the current page itself or from another page on the same domain. All modal content must be available when there is no JavaScript and in older browsers.

Content being loaded into the modal in sanitised prior to injection to the modal, meaning any inline JavaScript will not be run.

To include a button that closes the modal window, add the class a-button--cancel to the button; these buttons are not displayed if the user does not have JavaScript or is using an older browser.

When pulling in content from another page, if an id is included within the link, the content contained within the element with the matching id will be used to populate the modal, otherwise all the body will be used.

Always use t-accent-light t-accent-light--1 to reflect the latest design standards

Controling modals programatically

Modals can be controlled programatically to open, close or destroy a particular modal.

A simple event listener has been included with options to either just close the modal, or to close the modal and remove the loaded content from the page (thus clearing the form). This can be run using the following code:

utility.trigger( window, 'modal:close' );
utility.trigger( window, 'modal:destroy');

For more information on this, see our page on how to add Javascript to Framework components.

Alternatively, an API is available offering the following methods (please note that these are only available when associated with a valid modal link):

Method Description
open( modalLinkElement ) Open the modal for the modal link node element passed in.
close() Close the modal that is currently open.
destroy() Destroy the modal that is currently open.

For example:

document.addEventListener( 'frameworkready', function () {
	FRAMEWORK.require([ 'blocks/o-modal' ], function ( oModalModule ) {
		var modalLinkEl = document.querySelector( '#modalId' ),
			modalInstance = oModalModule.initInstance( document.documentElement );		modalInstance.open( modalLinkEl );
	});
});

Changing locale settings

Default text for the close link, loading indicator and content label for assistive technologies can be changed for a particular locale.

en: {
	oModal : {
		closeText : 'Close',
		loadingText : 'Please wait',
		contentLabel : 'Modal content',
	},
},

For more information on this, see our page on how to change locale settings within JavaScript.


Notes for testers

  • Ensure that links can be accessed via the mouse as well as via tabbing using the keyboard.
  • Use a screen reader to confirm that the links are understandable as to where they will be going when listed out of context of the page.
  • Ensure that when hovering over a link the style changes noticeably.
  • Ensure that when a link has focus the style changes noticeably.
  • Ensure that when a modal is open focus remains within the o-modal.
  • Ensure that when JavaScript is not available, or for older browsers such as IE8, that any links to open modals still take the user to the content (either on the page but not displayed in the modal, or via an external link).
  • Ensure that any modules such as show/hide, tabs etc that are contained within a modal's content work as expected.
  • Ensure it is clear how to close the window - by clicking outside of the window, by the use of prominent close buttons and also by using the ESC key.
  • There should be a clear visual distinction between the window and the background, which should be greyed out or faded. The user should not be able to to scroll or interact with background content.
  • Focus should be returned to its original place when the window is closed.

Classes overview

The following table gives you a quick overview of the CSS classes that can be applied.

Class Outcome Required Applied to Comments
.o-modal__content-container Base styling for in-page modal content. Hides content when JavaScript available Yes div  

Keyboard operations

TAB

Tabbing to an anchor should make the anchor clearly visually different so that the focus point on the page is obvious to the user

SPACE or ENTER

With focus on an anchor, pressing SPACE or ENTER will open the link. If the link is internal to the page it will scroll the page otherwise it will load the new page.

ESCAPE

With a modal visible, pressing ESCAPE will close the modal, if close has not been disabled.

Component releases

  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.11.0 (07/09/21)

Latest update:

  • updated: The modal positioning code has been updated to make use of CSS Flexbox, rather than relying on JavaScript to position the modal correctly. This simplifies the code and also makes the positioning of the modal more reliable, particularly when elements inside the modal cause it to change size.

Full version history

A full history of changes and enhancements detailing all minor and major updates to the component.

View full version history

Want something new in Framework, or to chat about an issue you're having with it?

Contact the team