Summarize this article with:
A clunky popup can tank your conversion rate. A smooth one keeps users engaged.
CSS modals examples show you exactly how to build dialog boxes, lightbox galleries, and overlay windows that work across devices and browsers.
This guide covers pure CSS solutions, JavaScript-enhanced patterns, and accessible modal dialog implementations following WCAG standards.
You will find copy-paste code snippets for checkbox hacks, :target selectors, fade animations, backdrop click handling, focus trapping, and responsive bottom sheets.
Each example includes working code you can drop into your project today.
What is a CSS Modal
A CSS modal is a popup window that overlays the main content to capture user attention.
It blocks interaction with the page underneath until closed or dismissed.
The modal component uses fixed positioning and z-index stacking to float above all other elements on screen.
Common uses include login forms, confirmation dialogs, image lightbox galleries, cookie consent notices, and call-to-action prompts.
Unlike inline content, a modal demands immediate response before the user can continue browsing.
Examples of CSS modals
Simple Confirmation Popup
See the Pen
Simple Confirmation Popup by Adventures in Missions (@adventuresinmissions)
on CodePen.
CSS Responsive Modal
See the Pen
CSS Responsive Modal by Thom Griggs (@thomgriggs)
on CodePen.
Draggable Translucent Modal
See the Pen
Draggable Translucent Modal by Jesse Couch (@designcouch)
on CodePen.
Details modal
See the Pen
Details modal by Niels Voogt (@NielsVoogt)
on CodePen.
Strikethrough Text With Explanations In Modal On Hover
See the Pen
Strike through explanations by eightarmshq (@EightArmsHQ)
on CodePen.
CSS Only Line Animated Modal
See the Pen
CSS Only Line Animated Modal by Tom (@TomJ1588)
on CodePen.
Pure CSS Animated Modals
See the Pen
Pure CSS Animated Modals by Tom (@TomJ1588)
on CodePen.
Simple Dialog Effects
See the Pen
Simple dialog effects by Ying Zhang (@dodozhang21)
on CodePen.
Pop Under Modal for Movie Ticket Snippet
See the Pen
Movie Ticket Animation – Loop 23 by Jorge Mendes (@jorgemoovein-the-bashful)
on CodePen.
CSS Modal
See the Pen
CSS Modal by Pete Nawara (@petebot)
on CodePen.
Pop-Up With Blurred Background Animation
See the Pen
Pop-up with blurred background animation by Benjamin Dalton (@jaeming)
on CodePen.
CSS Modal using :target Selector
See the Pen
CSS Modal using :target Selector by Homer Gaines (@xirclebox)
on CodePen.
Login Modal With Floating
See the Pen
Login Form with floating placeholder and light button by Saijo George (@SaijoGeorge)
on CodePen.
Pure CSS Modal Box
See the Pen
Pure CSS modal box by Kasper Mikiewicz (@Idered)
on CodePen.
Modal Animation Physics
See the Pen
Modal Animation Physics by Tey Tag (@pix3l)
on CodePen.
Animated Cookie Consent Modal Form
See the Pen
Evil Cookie Policy by Álex (@lerida)
on CodePen.
Material UI popup
See the Pen
Material UI popup by Mikael Ainalem (@ainalem)
on CodePen.
Morphing Modal Window
See the Pen
Morphing Modal Window by CodyHouse (@codyhouse)
on CodePen.
Pure CSS Modal
See the Pen
Pure CSS Modal by Mark Holmes (@SMLMRKHLMS)
on CodePen.
Pure CSS Modal + Slider
See the Pen
Pure CSS Modal + Slider by Marvin Orendain (@marv117)
on CodePen.
Basic CSS-Only Modal
See the Pen
Basic CSS-Only Modal by Timothy Long (@timothylong)
on CodePen.
Prompt Dialog With Background Blur
See the Pen
Prompt Dialog with background blur by Tuomas Hatakka (@ndne)
on CodePen.
Pure CSS Modal Popup
See the Pen
Pure CSS modal by Austin Lord (@ohnoitsaustin)
on CodePen.
Modal Window Destroy Concept
See the Pen
Modal window destroy concept by LegoMushroom (@sol0mka)
on CodePen.
Login Modal
See the Pen
login modal by Mert Cukuren (@knyttneve)
on CodePen.
Modal Dialog
See the Pen
Modal Dialog by David Fitas (@dfitzy)
on CodePen.
Pure CSS Modals
See the Pen
Pure CSS Modals by Akshay (@akzhy)
on CodePen.
Simple, Flexible And Responsive Flexbox-Based Modal
See the Pen
Simple, flexible, and responsive flexbox-based modal by Bryan Chalker (@bchalker)
on CodePen.
Pure css popup box
See the Pen
Pure css popup box by Prakash (@imprakash)
on CodePen.
Animated Popup Android Style
See the Pen
Animated Popup Android Style by Ashwin Saxena (@ashwinsaxena)
on CodePen.
Pop-up design
See the Pen
Pop-up design by fajjet (@fajjet)
on CodePen.
Pure CSS Modal window / Login & Sign up / Tabs / All Responsive
See the Pen
Pure CSS Modal window / Login & Sign up / Tabs / All Responsive by Andrew (@AndrewBeznosko)
on CodePen.
Popup Scroll Notification
See the Pen
Popup Scroll Notification by Zeinab Abounassif (@zeinab92)
on CodePen.
Folding Modal
See the Pen
Folding Modal by Blake Bowen (@osublake)
on CodePen.
Smart Welcome Popup
See the Pen
Smart Welcome Popup by CEMR NFT Creator (@sharjeet)
on CodePen.
Push Modal Idea
See the Pen
Push Modal Idea by Short (@short)
on CodePen.
Colourful Flower Popup Menu
See the Pen
Colourful Flower Popup Menu by Jasper LaChance (@jasperlachance)
on CodePen.
How Do CSS Modals Work
Modals rely on a few core CSS properties working together.
The backdrop overlay covers the entire viewport using position: fixed with top, left, right, and bottom set to zero.
A semi-transparent background (usually rgba black at 50% opacity) dims the page content behind it.
The modal content wrapper sits centered using flexbox or transform: translate techniques.
Visibility toggles between hidden and visible states through class changes.
The display property switches from none to block or flex when triggered.
Focus trapping keeps keyboard navigation locked inside the modal until it closes.
CSS Modal vs JavaScript Modal
Pure CSS modals use the :target selector or checkbox hack to toggle visibility without scripts.
JavaScript modals offer more control over open/close behavior, animation timing, and event handling.
| Feature | CSS-Only Modal (:target or checkbox) | JavaScript Modal |
| Code Complexity | Low (HTML/CSS only) | Medium to High |
| Browser Support | Excellent | Excellent |
| Animation Control | Limited to basic transitions | Full control (sequencing, physics) |
| Accessibility | Challenging (Requires tabindex hacks) | Better (Full ARIA & focus trap control) |
| Close on Backdrop | Tricky (requires invisible labels/anchors) | Easy (Event listeners) |
| Focus Management | Manual/Limited | Programmable (Auto-focus on open) |
| Esc Key Support | No (Native behavior) | Yes (Easy to implement) |
CSS-only works great for simple popups.
JavaScript becomes necessary when you need keyboard accessible modal dialogs with proper focus trapping.
CSS-Only Modal Examples
These modal popup examples work without any JavaScript dependency.
Pure CSS Modal with Checkbox Hack
This technique uses a hidden checkbox input paired with a label element to toggle modal visibility.
When checked, the :checked pseudo-class selector activates sibling styles that reveal the modal overlay.
“ <input type="checkbox" id="modal-toggle" class="modal-checkbox"> <label for="modal-toggle" class="modal-trigger">Open Modal</label>
<div class=”modal-overlay”> <div class=”modal-content”> <label for=”modal-toggle” class=”close-btn”>×</label> <h3>Modal Title</h3> <p>Your content here.</p> </div> </div> `
` .modal-checkbox { display: none; }
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.6); opacity: 0; visibility: hidden; transition: opacity 0.3s, visibility 0.3s; display: flex; align-items: center; justify-content: center; }
.modal-checkbox:checked ~ .modal-overlay { opacity: 1; visibility: visible; }
.modal-content { background: #fff; padding: 2rem; border-radius: 8px; max-width: 500px; width: 90%; } `
Limitation: URL doesn’t change, so browser back button won’t close the modal.
CSS Modal with :target Selector
The :target pseudo-class activates when the URL hash matches an element’s ID.
Clicking an anchor link with href=”#modal” triggers the open state.
` <a href="#demo-modal" class="open-modal">Open Modal</a>
<div id=”demo-modal” class=”modal-wrapper”> <div class=”modal-box”> <a href=”#” class=”close-modal”>×</a> <h3>Target Modal</h3> <p>Content goes here.</p> </div> </div> `
` .modal-wrapper { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity 0.25s ease; }
.modal-wrapper:target { opacity: 1; pointer-events: auto; }
.modal-box { background: white; padding: 30px; border-radius: 6px; position: relative; max-width: 450px; } `
Back button closes this modal since it modifies browser history.
CSS Modal with :focus-within
This approach shows the modal when any child element receives focus.
Works well for form modal popup patterns triggered by input fields.
` .modal-container:focus-within .modal-panel { opacity: 1; visibility: visible; transform: scale(1); }
.modal-panel { opacity: 0; visibility: hidden; transform: scale(0.9); transition: all 0.2s ease-out; } `
Keyboard users can tab into the modal naturally.
Screen readers announce the focused content properly.
JavaScript-Enhanced Modal Examples
Adding HTML structure with JavaScript control unlocks better user experience patterns.
Vanilla JavaScript Modal
A simple toggle function handles the open modal and hide modal states.
` <button class="trigger-btn" data-modal="myModal">Open</button>
<div id=”myModal” class=”modal”> <div class=”modal-dialog”> <button class=”modal-close”>×</button> <div class=”modal-body”> <h3>Modal Heading</h3> <p>Modal content here.</p> </div> </div> </div> `
` const triggers = document.querySelectorAll('[data-modal]'); const closeButtons = document.querySelectorAll('.modal-close');
triggers.forEach(btn => { btn.addEventListener(‘click’, () => { const modalId = btn.dataset.modal; document.getElementById(modalId).classList.add(‘active’); }); });
closeButtons.forEach(btn => { btn.addEventListener(‘click’, () => { btn.closest(‘.modal’).classList.remove(‘active’); }); }); `
Event listeners respond to click events on trigger buttons and close buttons.
Modal with CSS Animations
Combine CSS keyframes with JavaScript class toggling for smooth CSS animation effects.
` @keyframes modalFadeIn { from { opacity: 0; transform: translateY(-20px) scale(0.95); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes overlayFadeIn { from { opacity: 0; } to { opacity: 1; } }
.modal.active { animation: overlayFadeIn 0.3s ease forwards; }
.modal.active .modal-dialog { animation: modalFadeIn 0.3s ease 0.1s forwards; } `
The fade effect and transform create a polished modal fade animation.
Staggered timing (0.1s delay) adds depth to the transition.
Modal with Backdrop Click to Close
Users expect clicking outside the modal content to dismiss it.
` document.querySelectorAll('.modal').forEach(modal => { modal.addEventListener('click', (e) => { if (e.target === modal) { modal.classList.remove('active'); } }); }); `
The event target check ensures clicks on .modal-dialog children don’t close it accidentally.
Adding stopPropagation on inner elements provides extra safety.
` .modal { cursor: pointer; }
.modal-dialog { cursor: default; } `
Cursor styles give visual feedback about clickable zones.
Accessible Modal Examples
Building an accessible modal dialog requires proper web accessibility patterns beyond visual styling.
Screen reader users and keyboard-only users depend on correct semantic markup.
ARIA Dialog Modal
The role=”dialog” attribute tells assistive technology this element is a modal window.
` <div id="accessible-modal" role="dialog" aria-modal="true" aria-labelledby="modal-title" aria-describedby="modal-desc" > <h2 id="modal-title">Confirm Action</h2> <p id="modal-desc">Are you sure you want to proceed?</p> <button class="confirm-btn">Yes</button> <button class="cancel-btn">Cancel</button> </div> `
The aria-labelledby connects the modal to its heading for screen reader announcement.
Setting aria-modal=”true” tells browsers to restrict interaction to the dialog.
Modal with Keyboard Navigation
Focus management keeps Tab key cycling within the modal boundaries.
` function trapFocus(modal) { const focusable = modal.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); const first = focusable[0]; const last = focusable[focusable.length - 1];
modal.addEventListener(‘keydown’, (e) => { if (e.key === ‘Tab’) { if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); } else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); } } if (e.key === ‘Escape’) { closeModal(modal); } }); } `
Escape key listener provides a standard exit method.
First focusable element receives focus when modal opens.
Responsive Modal Examples
Modal design must adapt across viewport sizes using media queries.
Full-Screen Mobile Modal
On small screens, modals work better as full-screen takeovers.
` .modal-content { width: 90%; max-width: 500px; max-height: 80vh; overflow-y: auto; }
@media (max-width: 480px) { .modal-content { width: 100%; height: 100%; max-width: none; max-height: none; border-radius: 0; } } `
Viewport units ensure the modal never exceeds screen boundaries.
Centered Modal with Flexbox
Flexbox centering works across all browsers without transform hacks.
` .modal-overlay { display: flex; align-items: center; justify-content: center; position: fixed; inset: 0; }
.modal-box { margin: 1rem; width: min(90%, 600px); } `
The min() function handles responsive design in a single line.
Bottom Sheet Modal for Mobile
Bottom sheets slide up from the screen edge, common in mobile-first design patterns.
` .bottom-sheet { position: fixed; bottom: 0; left: 0; right: 0; background: white; border-radius: 16px 16px 0 0; transform: translateY(100%); transition: transform 0.3s ease-out; }
.bottom-sheet.active { transform: translateY(0); }
.drag-handle { width: 40px; height: 4px; background: #ccc; border-radius: 2px; margin: 12px auto; } `
Touch gesture support requires JavaScript for drag-to-close behavior.
Styled Modal Variations
Visual treatments differentiate modal types and match brand aesthetics.
Glassmorphism Modal
The CSS glassmorphism effect uses backdrop-filter for frosted glass appearance.
` .glass-modal { background: rgba(255, 255, 255, 0.15); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 16px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); } `
Works best over colorful or image backgrounds.
Safari requires the -webkit prefix for backdrop-filter.
Dark Mode Modal
CSS custom properties enable theme switching without duplicate styles.
` :root { --modal-bg: #ffffff; --modal-text: #1a1a1a; --modal-border: #e0e0e0; }
@media (prefers-color-scheme: dark) { :root { –modal-bg: #1e1e1e; –modal-text: #f0f0f0; –modal-border: #333333; } }
.modal-content { background: var(–modal-bg); color: var(–modal-text); border: 1px solid var(–modal-border); } `
The prefers-color-scheme query respects system preferences automatically.
Modal with Custom Close Button
Replace the default X with SVG icons for sharper rendering.
` <button class="close-btn" aria-label="Close modal"> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <path d="M18 6L6 18M6 6l12 12"/> </svg> </button> `
` .close-btn { position: absolute; top: 1rem; right: 1rem; background: none; border: none; cursor: pointer; padding: 0.5rem; border-radius: 50%; transition: background 0.2s; }
.close-btn:hover { background: rgba(0, 0, 0, 0.1); } `
The aria-label provides accessible naming for screen readers.
How to Create a CSS Modal Step by Step
Follow this sequence to build a production-ready modal component.
Step 1: HTML Structure
` <div class="modal-overlay" id="myModal"> <div class="modal-container" role="dialog" aria-modal="true"> <header class="modal-header"> <h2>Modal Title</h2> <button class="btn-close" aria-label="Close">×</button> </header> <div class="modal-body"> <p>Content here.</p> </div> <footer class="modal-footer"> <button class="btn-cancel">Cancel</button> <button class="btn-confirm">Confirm</button> </footer> </div> </div> `
Step 2: Base CSS Positioning
` .modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; opacity: 0; visibility: hidden; transition: opacity 0.25s, visibility 0.25s; z-index: 1000; }
.modal-overlay.open { opacity: 1; visibility: visible; } `
Step 3: Modal Content Styling
` .modal-container { background: white; border-radius: 8px; width: min(90vw, 500px); max-height: 85vh; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); }
.modal-header { padding: 1.25rem; border-bottom: 1px solid #eee; display: flex; justify-content: space-between; align-items: center; }
.modal-body { padding: 1.25rem; overflow-y: auto; }
.modal-footer { padding: 1rem 1.25rem; border-top: 1px solid #eee; display: flex; justify-content: flex-end; gap: 0.75rem; } `
Step 4: JavaScript Toggle
` const modal = document.getElementById('myModal'); const openBtn = document.querySelector('[data-open-modal]'); const closeBtn = modal.querySelector('.btn-close'); const cancelBtn = modal.querySelector('.btn-cancel');
function openModal() { modal.classList.add(‘open’); document.body.style.overflow = ‘hidden’; closeBtn.focus(); }
function closeModal() { modal.classList.remove(‘open’); document.body.style.overflow = ”; openBtn.focus(); }
openBtn.addEventListener(‘click’, openModal); closeBtn.addEventListener(‘click’, closeModal); cancelBtn.addEventListener(‘click’, closeModal); modal.addEventListener(‘click’, (e) => { if (e.target === modal) closeModal(); }); `
Step 5: Accessibility Testing
Test with keyboard only (Tab, Shift+Tab, Escape), then verify screen reader announcements using NVDA or VoiceOver.
Common CSS Modal Issues and Fixes
Scrolling Behind Modal
Background page scrolls while modal is open, breaking the overlay effect.
` // When opening document.body.style.overflow = 'hidden'; document.body.style.paddingRight = '15px'; // Prevent layout shift
// When closing document.body.style.overflow = ”; document.body.style.paddingRight = ”; `
iOS Safari needs position: fixed on body plus scroll position restoration.
Modal Not Centered on Screen
Transform-based centering fails with certain parent positioning contexts.
` / Problematic approach / .modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); }
/ Reliable fix / .modal-overlay { display: flex; align-items: center; justify-content: center; }
.modal { / No positioning needed / } `
Flexbox centering on the overlay parent avoids transform conflicts.
Z-Index Conflicts
Modal appears behind other fixed elements like sticky navigation or headers.
` / Create stacking context layers / :root { --z-dropdown: 100; --z-sticky: 200; --z-modal-backdrop: 900; --z-modal: 1000; --z-tooltip: 1100; }
.modal-overlay { z-index: var(–z-modal-backdrop); }
.modal-content { z-index: var(–z-modal); } `
CSS custom properties keep z-index values organized and predictable.
When to Use CSS Modals
Modals interrupt user flow, so reserve them for actions requiring immediate attention.
Good use cases:
- Confirmation dialogs before destructive actions
- CSS login forms and authentication flows
- Image CSS gallery lightbox viewers
- Cookie consent and privacy notices
- Video players requiring focused attention
- Multi-step CSS forms with progress indication
- Quick contact or feedback forms
Avoid modals for:
- Non-critical notifications (use toast messages instead)
- Content that users need to reference while interacting with the page
- Marketing popups on page load (hurts usability)
- Mobile screens where full-page views work better
Consider CSS tooltip or inline expansion for less intrusive alternatives.
FAQ on CSS Modals
What is a CSS modal?
A CSS modal is a popup window that overlays page content using fixed positioning and z-index stacking.
It displays dialog boxes, forms, or images while blocking interaction with elements underneath until dismissed.
How do I create a modal without JavaScript?
Use the :target pseudo-class or checkbox hack technique.
The :target method activates when a URL hash matches the modal’s ID. The checkbox approach toggles visibility using the :checked selector on a hidden input element.
How do I close a modal when clicking outside?
Add a click event listener to the overlay element. Check if event.target equals the overlay itself, not its children.
If true, remove the active class to hide the modal.
How do I center a modal on screen?
Apply display: flex with align-items: center and justify-content: center on the overlay container.
This method works reliably across browsers without transform: translate positioning hacks that can cause blurry text.
How do I make a modal accessible?
Add role=”dialog” and aria-modal=”true” attributes. Connect the heading with aria-labelledby.
Implement focus trapping to keep keyboard navigation inside the modal. Include an Escape key listener for closing. Follow the web accessibility checklist guidelines.
How do I add animations to a modal?
Use CSS transitions on opacity and transform properties for fade and slide effects.
Define @keyframes for complex CSS text animations or entrance sequences. Apply animation property when the active class toggles.
How do I prevent scrolling behind a modal?
Set document.body.style.overflow = ‘hidden’ when the modal opens.
Reset to empty string when closing. Add padding-right equal to scrollbar width to prevent layout shift on Windows browsers.
What is the difference between a modal and a popup?
Modals block page interaction until closed, requiring user response. Popups can appear without blocking, like tooltips or notifications.
Modals use backdrop overlays. Popups often position near trigger elements.
How do I create a responsive modal?
Use width: min(90vw, 500px) for fluid sizing. Set max-height with overflow-y: auto for scrollable content.
Apply full-screen styles on mobile using media queries at smaller breakpoints.
How do I trap focus inside a modal?
Query all focusable elements inside the modal container. On Tab keypress at the last element, move focus to the first.
On Shift+Tab at the first element, move focus to the last. This creates a loop.
Conclusion
These CSS modals examples give you production-ready code for every common use case.
Start with pure CSS techniques if you need simple popup windows without dependencies. Add DOM manipulation and event listeners when you need backdrop click detection, keyboard navigation, or complex opacity transitions.
Accessibility matters. Always include ARIA attributes, focus management, and Escape key handlers.
Test your modal component across browsers for cross-browser compatibility. Check fixed positioning behavior on iOS Safari. Verify z-index stacking against your CSS header and other layered elements.
The best modal feels invisible. Users complete their task and move on without friction.
Pick a pattern from this guide, customize the styling, and ship it.
