CSS :modal Pseudo-Class
The CSS :modal pseudo-class selects an element that is currently displayed in a modal state. It is commonly used to style an HTML dialog opened with showModal(), allowing the dialog to receive different styling while interaction with the rest of the document is blocked.
:modal Syntax
selector:modal {
property: value;
}
The :modal pseudo-class is added directly to a selector without a space. It matches an element only while that element is in a modal state.
Basic Example
dialog:modal {
border: 2px solid #006699;
}
This rule adds a blue border to an HTML dialog while it is displayed modally.
Background Example
dialog:modal {
background-color: #eaf6fc;
}
This rule changes the background color of a modal dialog.
Class Selector Example
.confirmation:modal {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}
This rule adds a shadow to an element with the confirmation class while it is modal.
How :modal Works
The :modal pseudo-class matches elements placed in a modal state by the browser. While a modal element is active, interaction with the rest of the document is restricted.
Modal State
A modal element requires the user to interact with or dismiss it before returning to the underlying document.
HTML Dialog Example
<dialog id="example-dialog">
<p>This is a modal dialog.</p>
<button type="button" id="close-dialog">Close</button>
</dialog>
JavaScript Example
const dialog = document.getElementById("example-dialog");
dialog.showModal();
Calling showModal() opens the dialog in a modal state. The dialog then matches :modal.
Automatic State Changes
When the dialog is closed, it stops matching :modal. No manual CSS class changes are required.
Top Layer
A modal dialog is placed in the browser's top layer, allowing it to appear above ordinary document content.
Modal Dialogs
The HTML <dialog> element provides a built-in way to create modal and nonmodal dialogs.
HTML Example
<button type="button" id="open-dialog">Open Dialog</button>
<dialog id="example-dialog">
<h2>Dialog Heading</h2>
<p>This dialog opens in a modal state.</p>
<button type="button" id="close-dialog">Close</button>
</dialog>
CSS Example
dialog:modal {
padding: 20px;
border: 2px solid #006699;
border-radius: 6px;
}
JavaScript Example
const dialog = document.getElementById("example-dialog");
document.getElementById("open-dialog").addEventListener("click", () => {
dialog.showModal();
});
document.getElementById("close-dialog").addEventListener("click", () => {
dialog.close();
});
Clicking the Open Dialog button displays the dialog modally. The CSS rule applies until the dialog closes.
Built-In Dialog Behavior
Modal dialogs provide built-in focus handling, keyboard dismissal behavior, and restrictions on interaction with the underlying document.
The showModal() Method
The JavaScript showModal() method opens an HTML dialog as a modal dialog.
JavaScript Syntax
dialog.showModal();
Opening a Dialog
const dialog = document.querySelector("dialog");
dialog.showModal();
The browser displays the dialog in the top layer and makes the rest of the document inert while the modal dialog is active.
Closing a Dialog
dialog.close();
Closing the dialog removes its modal state and causes it to stop matching :modal.
The Escape Key
Users can normally dismiss a modal dialog with the Escape key. Applications can handle the dialog's cancel event when appropriate.
Important Distinction
Using showModal() opens a modal dialog. Using show() opens a nonmodal dialog instead.
Modal vs. Nonmodal Dialogs
The <dialog> element can be opened in two different modes.
Comparison
| Method | Behavior | Matches :modal |
|---|---|---|
showModal() |
Opens a modal dialog and makes the rest of the document inert. | Yes |
show() |
Opens a nonmodal dialog without blocking the rest of the document. | No |
close() |
Closes an open dialog. | No |
CSS Example
dialog {
border: 1px solid #999;
}
dialog:modal {
border: 3px solid #006699;
}
Both modal and nonmodal dialogs can receive the general border. Only modal dialogs receive the thicker blue border.
The open Attribute
The open attribute indicates that a dialog is open, but it does not by itself make the dialog modal.
:modal vs. :open
The :modal and :open pseudo-classes describe different element states.
Comparison
| Selector | Matching Condition |
|---|---|
:modal |
The element is displayed in a modal state. |
:open |
The element is in an open state. |
CSS Example
dialog:open {
padding: 20px;
}
dialog:modal {
border: 2px solid #006699;
}
The first rule applies when the dialog is open, whether modal or nonmodal. The second applies only while the dialog is modal.
Related Elements
The :open pseudo-class can also match other elements with an open state, such as expanded <details> elements.
Choosing Between Them
Use :modal when styling depends on modal behavior. Use :open when styling depends on whether an element is open.
Styling the Backdrop
A modal dialog can display a backdrop behind it. The CSS ::backdrop pseudo-element styles this area.
CSS Example
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
This rule applies a translucent dark background behind a modal dialog.
Combining :modal and ::backdrop
dialog:modal {
border: 2px solid #006699;
}
dialog:modal::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
The first rule styles the modal dialog. The second styles its backdrop only while the dialog is modal.
Backdrop vs. Dialog
The :modal pseudo-class selects the modal element itself. The ::backdrop pseudo-element selects the backdrop generated behind an element in the top layer.
Visual Clarity
A backdrop can help distinguish the active modal dialog from the underlying page content.
Fullscreen Elements
The :modal pseudo-class is not limited to HTML dialogs. Elements displayed using the Fullscreen API can also match :modal.
JavaScript Example
const element = document.getElementById("fullscreen-content");
element.requestFullscreen();
When the element enters fullscreen mode, it can match both :fullscreen and :modal.
CSS Example
:fullscreen {
background-color: #fff;
}
:fullscreen:modal {
padding: 20px;
}
The first rule styles fullscreen elements. The second applies when an element matches both pseudo-classes.
Fullscreen vs. Dialog
Fullscreen elements and modal dialogs have different behaviors, but both can restrict interaction with other document content.
Choosing a Selector
Use :fullscreen when styling specifically for fullscreen presentation. Use :modal when styling based on modal state.
:modal Specificity
The :modal pseudo-class contributes a specificity of 0-1-0.
Specificity Examples
| Selector | Specificity |
|---|---|
:modal | 0-1-0 |
dialog:modal | 0-1-1 |
.confirmation:modal | 0-2-0 |
dialog:open:modal | 0-2-1 |
#example-dialog:modal | 1-1-0 |
dialog:modal::backdrop | 0-1-2 |
Specificity Example
dialog {
border: 1px solid #999;
}
dialog:modal {
border: 2px solid #006699;
}
When both selectors match and other cascade factors are equal, the :modal rule takes precedence because it has greater specificity.
Practical Uses
The :modal pseudo-class is useful for styling interfaces that temporarily require the user's attention.
Confirmation Dialogs
dialog.confirmation:modal {
border: 2px solid #006699;
}
Emphasize a confirmation dialog while it is modal.
Form Dialogs
dialog.form-dialog:modal {
padding: 24px;
background-color: #fff;
}
Apply modal-specific spacing and background styling to a form dialog.
Image Previews
dialog.image-preview:modal {
max-width: 90vw;
max-height: 90vh;
}
Constrain the dimensions of a modal image preview.
Backdrop Styling
dialog:modal::backdrop {
background-color: rgba(0, 0, 0, 0.6);
}
Dim the background while a modal dialog is active.
State-Based Styling
Apply different styles to a dialog depending on whether it is open modally or nonmodally.
Limitations
The :modal pseudo-class matches only elements that are in a modal state recognized by the browser.
Not Every Dialog Is Modal
A dialog opened with show() does not match :modal.
The open Attribute Is Not Enough
Adding the open attribute does not make a dialog modal.
CSS Cannot Create Modal Behavior
Styling an element with a high z-index or fixed positioning does not make it match :modal.
State Depends on Browser APIs
For HTML dialogs, the modal state is normally established with showModal().
Not a General Overlay Selector
Custom overlays built entirely with ordinary HTML and CSS do not automatically match :modal.
Backdrop Styling Is Separate
Use ::backdrop to style the area behind a modal element.
Accessibility
Modal interfaces should be accessible to keyboard users and assistive technologies.
Use Native Dialogs
Prefer the HTML <dialog> element and showModal() when a modal dialog is appropriate. They provide built-in modal behavior and focus handling.
Provide an Accessible Name
<dialog aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm Action</h2>
<p>Do you want to continue?</p>
</dialog>
Associate the dialog with a visible heading or another appropriate accessible label.
Provide a Close Control
Include a clearly labeled way to dismiss the dialog when dismissal is appropriate.
Keyboard Interaction
Ensure users can operate the dialog with a keyboard and return to the underlying content after closing it.
Focus Visibility
dialog button:focus-visible {
outline: 2px solid #006699;
outline-offset: 2px;
}
Keep keyboard focus indicators visible inside modal dialogs.
Avoid Unnecessary Modals
Use modal dialogs only when the user must complete or dismiss an interaction before continuing with the underlying page.
Best Practices
- Use
:modalwhen styling depends on an element's actual modal state. - Use
showModal()to open native HTML dialogs modally. - Use
show()when a nonmodal dialog is appropriate. - Use
:openfor styles that should apply to both modal and nonmodal open dialogs. - Use
::backdropto style the background behind a modal element. - Provide an accessible name and appropriate close controls.
- Keep keyboard focus indicators visible.
- Use
:fullscreenfor styles specific to fullscreen elements. - Do not assume an ordinary overlay or high
z-indexcreates modal behavior.
:modal Example
This example opens an HTML dialog using showModal(). The :modal pseudo-class applies a blue border and shadow while the dialog is modal. The ::backdrop pseudo-element dims the page behind it.
HTML
<button type="button" id="open-modal">Open Modal Dialog</button>
<dialog id="modal-demo" aria-labelledby="modal-title">
<h2 id="modal-title">Modal Dialog</h2>
<p>This dialog is displayed in a modal state.</p>
<button type="button" id="close-modal">Close Dialog</button>
</dialog>
CSS
#modal-demo {
max-width: 260px;
padding: 20px;
border: 1px solid #999;
border-radius: 6px;
}
#modal-demo:modal {
border: 3px solid #006699;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}
#modal-demo::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
JavaScript
const dialog = document.getElementById("modal-demo");
document.getElementById("open-modal").addEventListener("click", () => {
dialog.showModal();
});
document.getElementById("close-modal").addEventListener("click", () => {
dialog.close();
});
Browser Result
Note: Click Open Modal Dialog to display the dialog. While it is open modally, the dialog matches :modal. Click Close Dialog or press Escape to dismiss it.
Browser Support
Baseline: Widely available. The :modal pseudo-class is supported in modern versions of Chrome, Edge, Firefox, Safari, and other major browsers.
For current compatibility information, visit Can I Use? .
Specifications
The :modal pseudo-class is defined in CSS Selectors Level 4 as an element state pseudo-class. It matches elements that are in a modal state.
