DEV Community

Cover image for Creating a CSS modal window (pop-up) step-by-step
Pachi 🪐 (she/her/ela)
Pachi 🪐 (she/her/ela)

Posted on

Creating a CSS modal window (pop-up) step-by-step

Hello again to you, how are you doing today?

I am pretty good.
I spent good part of last week learning about Modals for my internship project, so I thought I would share that with you.

First, I didn't know what a modal was until I asked my Divaloper sister-in-life for help with my project, so maybe you don't know either.
Modal windows are kinda Pop-ups. When you click in something, it opens a window with information.

For my project, I need a card with information to open when a line from a table gets a click. Later in my experiments I found out this cannot be done with CSS only, because of the line element. But simple modals CAN be made with CSS only, so I will talk about those today, because I love pure CSS and its underestimated super powers.

I am still learning myself, and writing tutorials is also new to me, so bear with me ok?

I will give a simple example.


First we need to create our button.
I am just putting a link inside a Div.

  <a href="#modal">Open Modal</a>
Enter fullscreen mode Exit fullscreen mode

The link gets the href #modal because when clicked it will open our modal div, that we will create now:

<div id="modal">
  <div class="modal__window">
      <a class="modal__close" href="#">X</a>
      <h2>Please to meet you!</h2>
      <p>Hello there, I am a nice Modal Window.</p> 
Enter fullscreen mode Exit fullscreen mode

The div with the ID of modal is our container and the div with the class modal_window is the window that we want to display.
Note this second has a class of modal
_close It is the X on the corner that will close our Modal Window when we want to exit it, to it has a href of #

This is the very basic HTML we need, now let's dive into the CSS.


Let's start by styling out #modal div

#modal {
    position: fixed;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    background-color: rgba(0,0,0,.5);
    display: flex;
    justify-content: center;
    align-items: center;
Enter fullscreen mode Exit fullscreen mode

This will be the background of out window, so the position is fixed because we want it to remain in place. We have a top and left of 0 and the width and height are at 100% because we want this to cover the whole page.
The chosen background color will give us some transparency, so we can still see the contents of our main page.
Display flex, justify-content and align-items are just so our window will be in the center.

SO here is what we have so far:

The modal is created and styled.
now we want to style the window:

.modal__window {
  position: relative;
  background-color: white;
  padding: 4em 2em;

.modal__close {
  position: absolute;
  top: -30px;
  right: 0;
Enter fullscreen mode Exit fullscreen mode

Here we make the window look like a nice card and we position the X that will close the card, and we have this

Now, let's get down to business.
We need to make the modal disappear and just show up when our link is clicked.

#modal:not(:target) {
    visibility: hidden;
    opacity: 0;
Enter fullscreen mode Exit fullscreen mode

This piece of code just says that when #modal is not the target, it stays hidden. So now it will open only when is is the targed, meaning, when we click in our link.
And here is our endgame:

To summarize

We need a link,
we need an element inside a container (in this case, a div inside a div).
We give the container an ID, that was pass as the href of our link.
We use :not(:target) to hide our container until the link is clicked.
And we use another link with href of # to close our modal window.

Are you still with me?

Starlight opening a door and popping up to see who is there

Thank you for bearing with me, this is my first tentative at more technical posts. Plus writing it all down helps me to understand and retain the process better.
Thanks again for reading,

Happy Monday,

Discussion (9)

hackergaucho profile image
Hacker Gaucho • Edited on

it is relevant to say that dialog element (modal) is available natively in Chrome and Opera since 2014 and Edge since 2020, in other browsers we can use the dialog-polyfill

pachicodes profile image
Pachi 🪐 (she/her/ela) Author

Thank you for this info Anderson!

idoshamun profile image
Ido Shamun

This is a very nice CSS trick! I was not familiar with the :target selector. One thing we have to bear in mind is the aspect of accessibility which is missing here and like Anderson mentioned is available within the scope of the dialog element

aminmansuri profile image

Cool, I guess these days we could build a whole collapsible menubar without a single line of Javascript.

brendan8c profile image
Сова • Edited on

Close the current window by clicking on the gray area.
The gray area is the non-shaped area.
I used JavaScript
.#modal - This is a gray blackout area.

let writeForm = document.getElementById("write");
document.onclick = function(e) {
    if ( != writeForm && !writeForm.contains( {
    }; !== writeForm, !writeForm.contains(;
Enter fullscreen mode Exit fullscreen mode

How to do this in pure "css" I don't have idea..

utterhuman profile image
Serge Paskal • Edited on

Great article.
I didn't know neither about :target (supports from Chrome 1) nor <dialog> 🤦 shame on me.
Speaking about the code, just noticed your modal behaves different than the one from MDN: click to grey area doesn't close the popup (::backdrop in case of dialog element). Styling .modal__close:before, .modal__close:after (with z-index) and moving .modal__close itself to #modal's children level do the trick.

supersmartat profile image
Andreas Huber

If anyone needs a quickfix - i used the onclick to fix this background closing. It not plain css of course, but it improves usability for my application:

I extended the same logic with
<div id="modal" onclick="location.href='#'"; >
finally the grey background closes like the X before.

davidvalenciait profile image

Buen code! Gracias

kuruguru profile image

Thank you for this. Is it also possible to show the window at the start of the page (and then just close with the x) .. so that I do not have to push the button. Thanks for your support.