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.

FeatureCSS-Only Modal (:target or checkbox)JavaScript Modal
Code ComplexityLow (HTML/CSS only)Medium to High
Browser SupportExcellentExcellent
Animation ControlLimited to basic transitionsFull control (sequencing, physics)
AccessibilityChallenging (Requires tabindex hacks)Better (Full ARIA & focus trap control)
Close on BackdropTricky (requires invisible labels/anchors)Easy (Event listeners)
Focus ManagementManual/LimitedProgrammable (Auto-focus on open)
Esc Key SupportNo (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.

Author

Bogdan Sandu specializes in web and graphic design, focusing on creating user-friendly websites, innovative UI kits, and unique fonts.Many of his resources are available on various design marketplaces. Over the years, he's worked with a range of clients and contributed to design publications like Designmodo, WebDesignerDepot, and Speckyboy, Slider Revolution among others.