Lightbox Dialog
A modal window which dims out the main page behind it.
Last updated
A modal window which dims out the main page behind it.
Last updated
In traditional desktop operating systems, a lightbox dialog is a child-window that typically exists to communicate information to the user, display a prompt for input, or allow the user to verify or cancel an action.
Whilst these specific cases are also valid and true on the web, we also see a wide variety of other custom uses. For example, a dialog itself might contain an entire full page-like experience, a video, image gallery, navigation or settings.
There are various ways to visually present a dialog. The version here is the "lightbox" version. A dialog that visibly dims out the rest of the page while the dialog is open.
Experience the pattern in action on our eBay MIND patterns examples website.
View the required markup structure by viewing the bones GitHub project.
lightbox-dialog: the pattern as a whole, comprised of the following sub parts
parent window: the page containing the button that opens the dialog
dialog button: the button that opens the child window
child window: the overlay containing the dialog content
title: the title of the child window
modality: modal or non-modal, dialogs with a mask are always modal
mask: CSS effect that visibly dims out the parent window content
dismiss button: button that dismisses and hides the lightbox
A lightbox-dialog is typically opened in one of two ways:
Click-activated: explicitly opened and closed by clicking the button
System-activated: automatically opened by the system/application on page load or at some other arbitrary time
Opening modal dialogs that are not requested by user (i.e. system-activated) are a violation of WCAG Guideline 3.2.5 (Level AAA) and therefore should be reserved for exceptional circumstances only.
Lightbox dialog must not be opened on hover or focus of button.
Lightbox dialog must be opened on click-event of button or via an application event.
Lightbox dialog must contain a dismiss button.
Lightbox dialog must contain at least one interactive element (this can be the dismiss button).
Lightbox dialog must be clearly labelled by an onscreen heading/title
Lightbox dialog must start heading hierarchy at level 2.
This section provides interaction design for keyboard, screen reader and pointing devices.
If dialog button has focus, ENTER
or SPACE
key must open lightbox dialog.
When lightbox dialog opens, focus must move to the dismiss button.
Lightbox dialog must confine TAB
and SHIFT-TAB
to focusable elements of child window.
Pressing ESC
key must close lightbox dialog (unless the currently focussed element has existing ESC
key behaviour).
Dialog button must receive focus when lightbox dialog is closed.
Dialog button must not announce 'has popup'. A dialog is not considered a popup (i.e aria-haspopup="true"
is not valid in this context).
Focussed element should be announced when child window opens (via focus management).
Title must be announced when lightbox dialog opens.
Virtual cursor must be confined within child window.
Assistive technology might announce "Entering/leaving dialog" (or words to those affect) when focus enters or leaves the lightbox dialog respectively.
Clicking dialog button must open lightbox dialog.
Clicking mask can dismiss lightbox dialog.
HTML does provide a <dialog>
tag, but at the time of writing this tag does not have good cross browser support.
Button
We are going to add a button element that opens the lightbox dialog when clicked.
We have added a custom data attribute called data-dialog
. The value of this attribute references the ID of the dialog element and will be used by JavaScript (more on that later).
Dialog Role
The root element of the lightbox dialog must have a role of "dialog".
Hidden State
The lightbox dialog must have a property of hidden
to prevent it from being displayed on page load.
To display the dialog, simply remove this property. This property can be used as a hook for CSS transitions.
Child Window
The child window element contains the actual dialog content.
Header and Body
Next we create header and main structure, mimicking the structure of the main parent window.
Title
Every dialog must be labelled. We can use aria-labelledby to point to a suitable labelling element inside of our dialog.
Alternatively, if no suitable heading or labelling element exists, we can specify the label in an aria-label property instead:
Close Button
Every dialog requires some form of close/dismiss button. For a lightbox dialog, this button should be placed in the header.
There are many different ways to visually, and uniquely, style a lightbox dialog. The most important aspects for accessibility are the mask and the hidden state.
Dialog Mask
The mask creates a visual distinction between the overlay content in the foreground, and the page content in the background. It also prevents pointing devices from interacting with the page content behind the window.
The mask does not prevent keyboard or screen reader from accessing the page content behind the window - we will need JavaScript for that.
Hide and Show
A dialog is made visible simply by toggling its hidden
attribute.
CSS animation of the dialog and mask is outside the scope of this guide.
Modality for Keyboard
A lightbox dialog is always modal. A modal dialog must prevent keyboard focus moving from the child window to the parent window. In addition, keyboard focus must wrap from the last interactive element in the child window back to the first, and vice versa.
There are several different JavaScript techniques to achieve such behaviour. We provide an example JavaScript module, called makeup-keyboard-trap.
Modality for Screen Reader
While in an open state, any content that is not inside of the child window must be hidden from screen reader users. This can be achieved by applying aria-hidden="true"
to any non direct-ancestor nodes in the DOM.
Remember to unhide these elements when the lightbox dialog is closed, otherwise the main page will be completely hidden & inaccessible to screen readers.
Again, we provide an example module, called makeup-screenreader-trap, to assist with this behaviour.
Prevent Page Scroll
It is desirable to prevent the background page from scrolling when interacting with the foreground dialog content. This can be achieved with a class that applies overflow:hidden
to the html body.
The presence of this class would be toggled by our JavaScript on dialog hide/show event.
ESC Key
Pressing the ESC
key while focus is on the dismiss button, or any other interactive element that does not already have ESC
key behaviour, should close the dialog.
Any nested widgets should take care to prevent ESC
event from bubbling.
Returning Focus
When the lightbox dialog is closed, keyboard focus should return to the dialog button in the main page.
NOTE: dialog-close
is a custom event fired by the lightbox dialog widget.
We have some experimental JavaScript modules that may assist you with creation of an accessible dialog widget:
Useful for implementing modal behaviour for keyboard
Useful for implementing modal behaviour for screen reader
Combines keyboard-trap and screenreader-trap
Useful for finding the list of focusable elements inside of the dialog
This section gives an overview of ARIA usage within the context of this pattern.
Informs the assistive technology that the user is inside of a dialog.
Conveys that the dialog is modal
Informs the assistive technology of the onscreen text used to label the dialog.
Use onscreen text to name the dialog (typically an h2 heading element).
Explicitly name the dialog, if no suitable onscreen text exists.
While the dialog is in an open state, aria-hidden is used to hide all non-dialog elements from assistive technology.