Overlay
Overview
The overlay component creates a full-page overlay layer that sits on top of the main content. It's commonly used as a backdrop for modals, dialogs, and other overlaid content to focus user attention and prevent interaction with underlying elements.
When to Use
✅ Use overlay when:
- Creating modal dialogs that require user focus
- Building custom popups or lightboxes
- Implementing loading states that block interaction
- Creating photo galleries or media viewers
- Building custom dropdown menus or megamenus
❌ Don't use overlay for:
- Simple tooltips (use the tooltip component)
- Inline notifications (use callout or snackbar)
- Page-level loading indicators (consider a dedicated loading component)
Examples
Basic Usage
The overlay is hidden by default. Set the open property to true to display it. Click the overlay to close it in this example.
<>
<dap-ds-button onClick={
() => {
const overlay = document.querySelector('#overlay-basic');
overlay.open = !overlay.open;
}
}>Toggle Overlay</dap-ds-button>
<dap-ds-overlay id="overlay-basic" onClick={
() => {
const overlay = document.querySelector('#overlay-basic');
overlay.open = false;
}
}>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: 'white',
textAlign: 'center'
}}>
<div>
<h2>Overlay Content</h2>
<p>Click anywhere to close</p>
</div>
</div>
</dap-ds-overlay>
</>
Custom Background Colors
Use CSS custom properties to customize the overlay's appearance. The --dds-overlay-background property controls the background color and opacity.
<>
<dap-ds-stack direction="row">
<dap-ds-button onClick={() => document.querySelector('#overlay-dark').open = true}>
Dark Overlay
</dap-ds-button>
<dap-ds-button onClick={() => document.querySelector('#overlay-blue').open = true}>
Blue Overlay
</dap-ds-button>
<dap-ds-button onClick={() => document.querySelector('#overlay-light').open = true}>
Light Overlay
</dap-ds-button>
</dap-ds-stack>
<dap-ds-overlay
id="overlay-dark"
style={{'--dds-overlay-background': 'rgba(0, 0, 0, 0.8)'}}
onClick={() => document.querySelector('#overlay-dark').open = false}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: 'white'
}}>
<h3>Dark Overlay (rgba(0, 0, 0, 0.8))</h3>
</div>
</dap-ds-overlay>
<dap-ds-overlay
id="overlay-blue"
style={{'--dds-overlay-background': 'rgba(0, 100, 200, 0.5)'}}
onClick={() => document.querySelector('#overlay-blue').open = false}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: 'white'
}}>
<h3>Blue Overlay (rgba(0, 100, 200, 0.5))</h3>
</div>
</dap-ds-overlay>
<dap-ds-overlay
id="overlay-light"
style={{'--dds-overlay-background': 'rgba(255, 255, 255, 0.9)'}}
onClick={() => document.querySelector('#overlay-light').open = false}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: 'black'
}}>
<h3>Light Overlay (rgba(255, 255, 255, 0.9))</h3>
</div>
</dap-ds-overlay>
</>
Custom Transitions
Control the overlay's animation with transition duration and timing function properties.
<>
<dap-ds-stack direction="row">
<dap-ds-button onClick={() => document.querySelector('#overlay-slow').open = true}>
Slow Transition (2s)
</dap-ds-button>
<dap-ds-button onClick={() => document.querySelector('#overlay-bounce').open = true}>
Bounce Effect
</dap-ds-button>
</dap-ds-stack>
<dap-ds-overlay
id="overlay-slow"
style={{
'--dds-overlay-transition-duration': '2s',
'--dds-overlay-background': 'rgba(100, 50, 150, 0.6)'
}}
onClick={() => document.querySelector('#overlay-slow').open = false}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: 'white'
}}>
<div>
<h3>Slow Transition</h3>
<p>Watch the 2-second fade animation</p>
</div>
</div>
</dap-ds-overlay>
<dap-ds-overlay
id="overlay-bounce"
style={{
'--dds-overlay-transition-duration': '0.8s',
'--dds-overlay-transition-timing': 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
'--dds-overlay-background': 'rgba(200, 100, 0, 0.6)'
}}
onClick={() => document.querySelector('#overlay-bounce').open = false}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: 'white'
}}>
<div>
<h3>Bounce Effect</h3>
<p>Custom cubic-bezier timing</p>
</div>
</div>
</dap-ds-overlay>
</>
Layered Overlays
Multiple overlays can be stacked using different z-index values. This is useful for nested modals or complex UI patterns.
<>
<dap-ds-stack direction="row">
<dap-ds-button onClick={() => document.querySelector('#overlay-layer1').open = true}>
Layer 1 (z-index: 1)
</dap-ds-button>
<dap-ds-button onClick={() => document.querySelector('#overlay-layer2').open = true}>
Layer 2 (z-index: 10)
</dap-ds-button>
<dap-ds-button onClick={() => document.querySelector('#overlay-layer3').open = true}>
Layer 3 (z-index: 100)
</dap-ds-button>
</dap-ds-stack>
<dap-ds-overlay
id="overlay-layer1"
style={{
'--dds-overlay-z-index': '1',
'--dds-overlay-background': 'rgba(255, 0, 0, 0.3)'
}}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%'
}}>
<div>
<h3>Layer 1 (Red)</h3>
<dap-ds-button onClick={() => document.querySelector('#overlay-layer1').open = false}>
Close
</dap-ds-button>
</div>
</div>
</dap-ds-overlay>
<dap-ds-overlay
id="overlay-layer2"
style={{
'--dds-overlay-z-index': '10',
'--dds-overlay-background': 'rgba(0, 255, 0, 0.3)'
}}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%'
}}>
<div>
<h3>Layer 2 (Green)</h3>
<dap-ds-button onClick={() => document.querySelector('#overlay-layer2').open = false}>
Close
</dap-ds-button>
</div>
</div>
</dap-ds-overlay>
<dap-ds-overlay
id="overlay-layer3"
style={{
'--dds-overlay-z-index': '100',
'--dds-overlay-background': 'rgba(0, 0, 255, 0.3)'
}}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%'
}}>
<div>
<h3>Layer 3 (Blue)</h3>
<dap-ds-button onClick={() => document.querySelector('#overlay-layer3').open = false}>
Close
</dap-ds-button>
</div>
</div>
</dap-ds-overlay>
</>
Modal Dialog with Overlay
Combining overlay with other components to create a centered modal dialog.
<>
<dap-ds-button onClick={() => document.querySelector('#overlay-modal').open = true}>
Open Modal Dialog
</dap-ds-button>
<dap-ds-overlay id="overlay-modal">
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
padding: '2rem'
}}>
<dap-ds-card style={{maxWidth: '500px', width: '100%'}}>
<dap-ds-stack>
<dap-ds-typography variant="h2">Confirm Action</dap-ds-typography>
<dap-ds-typography variant="body">
Are you sure you want to proceed with this action? This operation cannot be undone.
</dap-ds-typography>
<dap-ds-stack direction="row" justify="end">
<dap-ds-button
variant="outline"
onClick={() => document.querySelector('#overlay-modal').open = false}
>
Cancel
</dap-ds-button>
<dap-ds-button
danger
onClick={() => {
alert('Action confirmed!');
document.querySelector('#overlay-modal').open = false;
}}
>
Confirm
</dap-ds-button>
</dap-ds-stack>
</dap-ds-stack>
</dap-ds-card>
</div>
</dap-ds-overlay>
</>
Image Lightbox
Using overlay to create a simple image lightbox viewer.
<>
<dap-ds-button onClick={() => document.querySelector('#overlay-lightbox').open = true}>
View Image
</dap-ds-button>
<dap-ds-overlay
id="overlay-lightbox"
style={{'--dds-overlay-background': 'rgba(0, 0, 0, 0.9)'}}
onClick={() => document.querySelector('#overlay-lightbox').open = false}
>
<div style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
padding: '2rem'
}}>
<img
src="https://via.placeholder.com/800x600/667eea/ffffff?text=Sample+Image"
alt="Sample"
style={{
maxWidth: '100%',
maxHeight: '80vh',
borderRadius: 'var(--dds-radius-large)',
boxShadow: '0 20px 40px rgba(0,0,0,0.3)'
}}
/>
<dap-ds-typography
variant="body"
style={{color: 'white', marginTop: '1rem'}}
>
Click anywhere to close
</dap-ds-typography>
</div>
</dap-ds-overlay>
</>
Loading State
Creating a full-page loading indicator with overlay.
<>
<dap-ds-button onClick={() => {
const overlay = document.querySelector('#overlay-loading');
overlay.open = true;
setTimeout(() => {
overlay.open = false;
}, 3000);
}}>
Simulate Loading (3s)
</dap-ds-button>
<dap-ds-overlay
id="overlay-loading"
style={{'--dds-overlay-background': 'rgba(255, 255, 255, 0.95)'}}
>
<div style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
gap: '1rem'
}}>
<dap-ds-spinner size="lg"></dap-ds-spinner>
<dap-ds-typography variant="h3">Loading...</dap-ds-typography>
<dap-ds-typography variant="body" style={{color: 'var(--dds-text-neutral-subtle)'}}>
Please wait while we process your request
</dap-ds-typography>
</div>
</dap-ds-overlay>
</>
Custom Styling
The overlay component provides extensive customization options through CSS custom properties and parts.
CSS Custom Properties
<>
<dap-ds-button onClick={() => document.querySelector('#overlay-custom').open = true}>
Custom Styled Overlay
</dap-ds-button>
<dap-ds-overlay
id="overlay-custom"
style={{
'--dds-overlay-background': 'linear-gradient(135deg, rgba(102, 126, 234, 0.8) 0%, rgba(118, 75, 162, 0.8) 100%)',
'--dds-overlay-transition-duration': '0.5s',
'--dds-overlay-transition-timing': 'cubic-bezier(0.4, 0, 0.2, 1)',
'--dds-overlay-z-index': '999'
}}
onClick={() => document.querySelector('#overlay-custom').open = false}
>
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
color: 'white',
textAlign: 'center'
}}>
<div>
<h2>Gradient Overlay</h2>
<p>Custom background with smooth transitions</p>
</div>
</div>
</dap-ds-overlay>
</>
Advanced Styling with CSS Parts
Use the CSS ::part() selector to apply advanced styling to the overlay element. Try editing the CSS below:
Background ContentThis content will be overlaid
Overlay Content
Accessibility
Requirements
- Focus management: When overlay opens, focus should move to overlay content
- Keyboard support: ESC key should close the overlay (implement in parent component)
- ARIA attributes: The overlay automatically sets
aria-hidden based on open state
- Screen reader announcements: Announce when overlay opens/closes
Best Practices
- Ensure sufficient color contrast for overlay content
- Provide a clear way to close the overlay
- Consider users with motion sensitivity when using transitions
- Test with keyboard-only navigation
Importing
Importing React
Tree-Shakeable Imports
For optimal bundle sizes, use the tree-shakeable import syntax:
Attributes
| Property | Type | Default | Description |
|---|
open | boolean | false | The open state of the overlay. |
Slots
| Name | Description |
|---|
(default) | The content of the overlay. |
Events
| Event Name | Description | Type |
|---|
dds-before-open | Fires before the overlay opens. | CustomEvent |
dds-opened | Fires after the overlay opens. | CustomEvent |
dds-before-close | Fires before the overlay closes. | CustomEvent |
dds-closed | Fires after the overlay closes. | CustomEvent |
CSS Parts
| Part Name | Description |
|---|
overlay | The overlay element |
How to Use CSS Parts
You can style CSS parts using the ::part() pseudo-element selector:
Example usage:
CSS parts allow you to style internal elements of the component while maintaining encapsulation. Learn more in our styling guide.
CSS Custom Properties
| Property Name | Description |
|---|
--dds-overlay-z-index | Controls the z-index of the overlay (default: 1) |
--dds-overlay-background-color | Controls the background color of the overlay (default: var(--dds-black-10)) |
--dds-overlay-opacity-closed | Controls the opacity when overlay is closed (default: 0) |
--dds-overlay-opacity-open | Controls the opacity when overlay is open (default: 1) |
--dds-overlay-transition-duration | Controls the transition duration (default: var(--dds-transition-fast)) |
--dds-overlay-transition-timing | Controls the transition timing function (default: var(--dds-easing-ease-in-out)) |
How to Use CSS Custom Properties
CSS custom properties (CSS variables) can be set directly on the component or in your stylesheet:
Method 1: Inline styles (Quick customization)
Method 2: CSS classes (Reusable styles)
Method 3: Global theme customization
CSS custom properties inherit through the Shadow DOM, making them perfect for theming. Changes apply immediately without rebuilding.