Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Creating Modal Windows with Pure CSS: No JavaScript Required
Max Prilutskiy
Max Prilutskiy

Posted on

     

Creating Modal Windows with Pure CSS: No JavaScript Required

Wait, you can build modal windows without JavaScript? Yep, that's CSS secretly laughing at JavaScript behind its back. AtLingo.dev, we love diving into weird engineering rabbit holes that make other devs do a double-take.

Most developers wouldn't even think twice before reaching for a JavaScript library when they need a modal. But what if I told you there's this bizarre, oddball alternative hiding in plain sight? Pure CSS can pull off some surprisingly sneaky tricks that'll make you question everything you thought you knew about frontend development.

In this tutorial, we'll explore how to create fully functional modal windows using nothing but HTML and CSS. You can use it for fun, or in production. We'll be pushing CSS to do things it probably wasn't designed for, and that's exactly what makes this approach so deliciously unusual.

So, let's dive in!

Understanding the Modal Window Challenge

Modal windows are those overlay elements that pop up on top of your main content, usually demanding some kind of interaction before you can get back to what you were doing. You've seen them everywhere – login forms, image galleries, notifications, those annoying "SUBSCRIBE TO OUR NEWSLETTER" popups (though let's build less annoying ones, shall we?).

Traditionally, modals need JavaScript for three main things:

  1. Showing the modal when triggered
  2. Hiding the modal when dismissed
  3. Managing focus and keyboard interactions

So here's our challenge: how do we handle these state changes without JavaScript?

The answer comes from two clever CSS techniques that leverage built-in browser behaviors to create interactivity: the:target pseudo-class and what's affectionately known as the "checkbox hack."

The CSS Building Blocks

Before we start coding, let's get our heads around the core CSS concepts that make JavaScript-free modals possible.

The :target Pseudo-class

The:target pseudo-class is triggered when an element's ID matches the URL's hash fragment. In plain English? If your URL ends with#modal, any element withid="modal" will match the:target selector.

This gives us a way to change styles based on navigation state, which is perfect for showing and hiding modals. When someone clicks a link pointing to#modal, the browser navigates to that fragment, and we can use CSS to make the modal visible.

/* Hidden by default */.modal{opacity:0;pointer-events:none;}/* Visible when targeted */.modal:target{opacity:1;pointer-events:auto;}
Enter fullscreen modeExit fullscreen mode

The Checkbox Hack

The checkbox hack uses a hidden checkbox input and the:checked pseudo-class to toggle states. By connecting a label to the checkbox, we can create clickable elements that toggle the checkbox's state without JavaScript.

/* Hidden by default */.modal{opacity:0;pointer-events:none;}/* Visible when checkbox is checked */.modal-checkbox:checked~.modal{opacity:1;pointer-events:auto;}
Enter fullscreen modeExit fullscreen mode

Essential CSS Properties

Both techniques rely on several key CSS properties:

  1. Position: fixed - This takes the modal out of the document flow and positions it relative to the viewport, allowing it to overlay the entire page.

  2. Opacity & pointer-events - These control visibility and interaction. Settingpointer-events: none prevents the hidden modal from blocking clicks on elements beneath it.

  3. z-index - Ensures the modal appears above other content.

  4. Transitions - Adds smooth animations when showing and hiding the modal.

Now that we understand the building blocks, let's implement our first modal.

Building a Basic CSS Modal with :target

The:target approach is the simplest way to create a CSS-only modal. It requires minimal HTML and CSS, making it perfect for quick implementations.

Here's how it works:

  1. We create a link that points to the modal's ID
  2. When clicked, the browser navigates to that fragment
  3. The:target selector applies styles to make the modal visible
  4. Another link with an empty fragment (href="#") closes the modal

Let's build it step by step:

HTML Structure

<!-- Modal trigger button --><ahref="#modal-example"class="modal-trigger">Open Modal</a><!-- Modal container --><divid="modal-example"class="modal"><!-- Backdrop for closing the modal when clicking outside --><ahref="#"class="modal-backdrop"></a><!-- Modal content --><divclass="modal-content"><h2>Welcome to the Modal!</h2><p>This modal window is created using only HTML and CSS!</p><ahref="#"class="modal-close">Close Modal</a></div></div>
Enter fullscreen modeExit fullscreen mode

CSS Implementation

/* Modal container - hidden by default */.modal{position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.6);opacity:0;pointer-events:none;transition:opacity0.3sease;/* Center the modal content */display:flex;align-items:center;justify-content:center;z-index:100;}/* When the modal is targeted via URL hash, make it visible */.modal:target{opacity:1;pointer-events:auto;}/* Modal content box */.modal-content{background-color:white;padding:2rem;border-radius:6px;width:90%;max-width:500px;max-height:90vh;overflow-y:auto;box-shadow:05px30pxrgba(0,0,0,0.2);}/* Backdrop close link - covers the entire screen */.modal-backdrop{position:absolute;top:0;left:0;right:0;bottom:0;cursor:default;z-index:-1;/* Place behind modal content */}
Enter fullscreen modeExit fullscreen mode

Complete Working Example

For a fully functional implementation of this approach, check out ourfirst example. This example includes:

  • A clean, minimal design
  • Smooth fade-in/out transitions
  • The ability to close the modal by clicking outside it
  • Responsive behavior for all screen sizes

This implementation creates a modal that:

  • Appears when you click the "Open Modal" link
  • Can be closed by clicking the close button or anywhere outside the modal
  • Animates smoothly with a fade effect
  • Is centered on the screen with a semi-transparent backdrop

The beauty of this approach is its simplicity. With just a few lines of HTML and CSS, we've created a functional modal without a single line of JavaScript.

However, the:target method does have some limitations. The most notable is that it changes the URL by adding a hash fragment, which affects browser history. Each time you open and close the modal, a new entry is added to the browser's history, meaning users might need to click the back button multiple times to navigate away from the page.

For applications where this behavior is problematic, the checkbox hack offers an alternative.

The Checkbox Hack Alternative

The checkbox hack avoids URL changes by using a hidden checkbox input to track the modal's state. Here's how it works:

  1. A hidden checkbox controls the modal's visibility
  2. A label linked to the checkbox serves as the open button
  3. Another label linked to the same checkbox serves as the close button
  4. CSS selectors use the checkbox's:checked state to show or hide the modal

Let's implement this approach:

HTML Structure

<!-- Hidden checkbox for controlling modal state --><inputtype="checkbox"id="modal-toggle"class="modal-checkbox"><!-- Modal trigger button (label for the checkbox) --><labelfor="modal-toggle"class="modal-trigger">Open Modal</label><!-- Modal container --><divclass="modal"><!-- Modal content --><divclass="modal-content"><h2>Welcome to the Modal!</h2><p>This modal window uses the checkbox hack!</p><!-- Close button (another label for the same checkbox) --><labelfor="modal-toggle"class="modal-close">Close Modal</label></div></div>
Enter fullscreen modeExit fullscreen mode

CSS Implementation

/* Hide the checkbox input */.modal-checkbox{display:none;}/* Modal container - hidden by default */.modal{position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.6);opacity:0;pointer-events:none;transition:opacity0.3sease;/* Center the modal content */display:flex;align-items:center;justify-content:center;z-index:100;}/* When the checkbox is checked, make the modal visible */.modal-checkbox:checked~.modal{opacity:1;pointer-events:auto;}
Enter fullscreen modeExit fullscreen mode

Complete Working Example

For a fully functional implementation of the checkbox hack, check out oursecond example. This example includes:

  • A clean, modern design with a different color scheme
  • Scale animation for the modal content
  • No URL changes when opening/closing the modal
  • Responsive behavior for all screen sizes

The checkbox hack offers several advantages over the:target method:

  1. No URL changes or browser history entries
  2. More control over the modal's behavior
  3. Ability to create more complex interactions

However, it does require more HTML elements and careful consideration for accessibility. Without proper ARIA attributes, screen readers might not understand the relationship between the checkbox and the modal.

Enhancing Your Modal with Animations

Now that we have the basic functionality working, let's add some visual polish with CSS animations. Animations make the modal feel more responsive and provide visual cues about what's happening.

Here's how to add a simple entrance animation to our checkbox modal:

/* Modal content box with animation */.modal-content{background-color:white;padding:2rem;border-radius:6px;width:90%;max-width:500px;/* Initial state - scaled down */transform:scale(0.8);transition:transform0.3sease;}/* Animate to full size when visible */.modal-checkbox:checked~.modal.modal-content{transform:scale(1);}
Enter fullscreen modeExit fullscreen mode

This creates a subtle "pop" effect as the modal appears. You can get creative with different animation styles:

Slide-in Animation

.modal-content{/* Initial state - off-screen */transform:translateY(-50px);transition:transform0.3sease;}.modal-checkbox:checked~.modal.modal-content{transform:translateY(0);}
Enter fullscreen modeExit fullscreen mode

Fade-and-scale Animation

.modal-content{/* Initial state - transparent and small */opacity:0;transform:scale(0.9);transition:all0.3sease;}.modal-checkbox:checked~.modal.modal-content{opacity:1;transform:scale(1);}
Enter fullscreen modeExit fullscreen mode

Making Your Modal Responsive

For a truly polished modal, we need to ensure it works well on all device sizes. Here are some responsive design considerations:

/* Base styles for the modal content */.modal-content{width:90%;max-width:500px;padding:2rem;}/* Adjustments for small screens */@media(max-width:600px){.modal-content{width:95%;padding:1.5rem;}/* Smaller text on mobile */.modal-contenth2{font-size:1.5rem;}}
Enter fullscreen modeExit fullscreen mode

These adjustments ensure the modal remains usable on mobile devices, where screen real estate is limited.

Accessibility Considerations

While CSS-only modals are impressive, they do have accessibility limitations compared to JavaScript implementations. Here are some ways to improve accessibility:

  1. ARIA attributes - Addrole="dialog" andaria-modal="true" to the modal container.

  2. Focus management - This is challenging without JavaScript, but you can use the:focus-within pseudo-class to style the modal when it contains focused elements.

  3. Keyboard navigation - Ensure all interactive elements are tabbable and that the modal can be closed with keyboard actions.

<divclass="modal"role="dialog"aria-modal="true"aria-labelledby="modal-title"><divclass="modal-content"><h2id="modal-title">Accessible Modal Title</h2><!-- Modal content --></div></div>
Enter fullscreen modeExit fullscreen mode

Real-world Applications

CSS-only modals are unusual, however, they are perfect for several use cases:

  1. Image galleries - Click a thumbnail to show a larger version in a modal.
  2. Simple forms - Newsletter signups, contact forms, or login dialogs.
  3. Notifications and alerts - Display important messages to users.
  4. Content previews - Show a preview of content before navigating to a full page.

For more complex interactions, such as multi-step forms or modals that need to communicate with a server, you'll likely need JavaScript. But for many common use cases, CSS-only modals provide a lightweight, performant solution.

Browser Compatibility

The techniques we've covered work in all modern browsers. The:target pseudo-class has been supported since IE9, and the checkbox hack works in all browsers that support CSS3 selectors.

However, there are some edge cases to be aware of:

  1. Mobile browsers might handle the:target selector differently, especially regarding the back button behavior.
  2. Older browsers might not support some CSS features like flexbox or transitions.

Always test your modals across different browsers and devices to ensure consistent behavior.

Conclusion

Creating modal windows with pure CSS demonstrates the surprising power of modern CSS. It's pretty cool and unusual, that we can leverage the:target pseudo-class or the checkbox hack, to create interactive components that traditionally required JavaScript.

If you're open to using a bit of CSS, the benefits of this approach are clear:

  • Faster loading times (no JavaScript to download and parse)
  • Better reliability (works even when JavaScript fails)
  • Simpler maintenance (fewer moving parts)

While CSS-only modals do have limitations, particularly around complex interactions and accessibility, they're a valuable tool in any developer's toolkit. For many common use cases, they provide an elegant, lightweight solution that challenges our assumptions about what's possible with CSS alone.

Next time you need a simple modal, consider whether you really need JavaScript, or if CSS might be all you need. You might be surprised by how much you can accomplish with a few clever CSS tricks. ;)


Useful links:

Also:

Top comments(22)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
xwero profile image
david duymelinck
Learned to code in the wild west time of php 4, also the time xml and xpath where the new hot thing.
  • Location
    Belgium
  • Joined

I find it a bit strange that nobody mentioned thedialog html element.
It is better than using a div and it has javascript events.

If you are feeling adventurous the CSS tricks from this post can be used. Personally I would stick to the small amount of javascript you need to add to make the dialog working.

CollapseExpand
 
jesterly profile image
jesterly
  • Joined

Zero JS code is required if you use the Popover API with dialog element.

CollapseExpand
 
xwero profile image
david duymelinck
Learned to code in the wild west time of php 4, also the time xml and xpath where the new hot thing.
  • Location
    Belgium
  • Joined

Thank you for sharing that, I didn't know it existed. FromMDN I see it is an experimental feature.

Thread Thread
 
jesterly profile image
jesterly
  • Joined

You're welcome. It's only experimental if you use hint popovers:

developer.mozilla.org/en-US/docs/W...

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

If you are feeling adventurous the CSS tricks from this post can be used

Haha, yes, exactly!

We personally do use these tricks internally, but most of the time, from what we see, it's a design system / component library implementation detail.

CollapseExpand
 
anitaolsen profile image
Anita Olsen
Greetings! I am a retired hard of hearing hobbyist coder 😊 I am into learning new things, finance, reading, writing and playing video games.
  • Location
    Norway
  • Education
    Business School and an IB School of Economics
  • Work
    Volunteer DEV mod
  • Joined

This is just brilliant! Thank you for sharing with us! ✨

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

Thanks Anita :)

CollapseExpand
 
jswhisperer profile image
Greg, The JavaScript Whisperer
Specialist in performance oriented javascript architecture for web, mobile, client and server side. Passionate about realtime web.
• Edited on• Edited

Neat solution, I thought I'd fork your solution and demo a no js needed no css needed solution 🤯

I kid you not! I added CSS just to match your example, but it's not needed, and go for it disable js... still worksgithub

Read more here:dev.to/jswhisperer/invoker-command...

it's also hella accessible!

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined
• Edited on• Edited

nice! 🔥

CollapseExpand
 
anthonymax profile image
Anthony Max
🐜 Fetch API enjoyer
  • Education
    Unfinished bachelor's degree
  • Pronouns
    Anthony or Tony
  • Work
    HMPL.js
  • Joined

Great article!

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

Thanks Anthony!

CollapseExpand
 
nathan_tarbert profile image
Nathan Tarbert
I am a developer and open-source evangelist!
  • Location
    Florida, USA
  • Education
    Kingsland University
  • Work
    Community Engineer
  • Joined

pretty cool you can ditch js for stuff like this - honestly makes me wonder if i’m over-complicating my own setups. you think pushing css like this actually makes sites easier to maintain in the long run or nah?

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

Great question Nathan!

I think it boils down to how well this type of CSS is encapsulated in the code in the end.

I personally think CSS modals are elegant, though it isn't the most usual thing to do. :)

CollapseExpand
 
nevodavid profile image
Nevo David
Founder of Postiz, an open-source social media scheduling tool.Running Gitroom, the best place to learn how to grow open-source tools.
  • Education
    Didn't finish high school :(
  • Pronouns
    Nev/Nevo
  • Work
    OSS Chief @ Gitroom
  • Joined

Pretty cool seeing CSS pushed like this. Makes me want to mess around and see what else I can pull off without JS.

CollapseExpand
 
ryanguitar profile image
Ryan Els
Frontend Developer
  • Email
  • Location
    Cape Town
  • Work
    I have made my first professional website. at Security sector
  • Joined

Excellent article and well explained 😁👍🏻

From now on I won't make a modal any other way.

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

⚡⚡

CollapseExpand
 
lovit_js profile image
Lovit
Next-generation JavaScript error-handling library
  • Joined

Really loved how you explained both the :target method and the checkbox hack — super clear and practical. It’s amazing how much we can do with just CSS!

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

CSS is becoming a programming language 😅

CollapseExpand
 
veronica_prilutskaya_c597 profile image
Veronica Prilutskaya
  • Joined

Cool CSS trick!

CollapseExpand
 
maxprilutskiy profile image
Max Prilutskiy
Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

Yes, indeed!

CollapseExpand
 
nevodavid profile image
Nevo David
Founder of Postiz, an open-source social media scheduling tool.Running Gitroom, the best place to learn how to grow open-source tools.
  • Education
    Didn't finish high school :(
  • Pronouns
    Nev/Nevo
  • Work
    OSS Chief @ Gitroom
  • Joined

pretty cool seeing css pull this off - makes me want to rethink some of my usual stacks haha. you ever find yourself secretly hoping to kick more js out of your projects?

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Hacking on open source, with JavaScript and LLMs. Thoughts on software development, and unusual tech stuff.
  • Location
    San Francisco, California
  • Work
    Author of Lingo.dev
  • Joined

More fromMax Prilutskiy

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp