Learn how to create a simple responsive pop-up modal window using Vanilla JavaScript along with HTML and CSS **with a bit of **Flexbox.
- Create A Button That Opens Pop Up Modal Window
- Create Pop Up Modal Overlay
- Center Pop Up Modal Window To The Modal Overlay
- Open Up Pop Up Modal Window On Button Click
- Close/Hide Pop Up Modal Window On Button Click
- Hide Pop Up Modal Window When Modal Overlay Is Clicked
Create A Button That Opens Pop Up Modal Window
Declare a button HTML element with an id open-modal.
<button id="open-modal">Open Modal Window</button>
The goal is when a user presses this button, the pop-up modal window will open.
Style the button using CSS Flexbox and centre it on the screen.
* {
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
box-sizing: border-box;
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
button {
padding: 10px;
font-size: 1.1em;
background: #32bacf;
color: white;
border: none;
border-radius: 10px;
border: 1px solid rgba(0, 0, 0, 0.2);
cursor: pointer;
}
button:hover {
background: rgba(0, 0, 0, 0.7);
}
Create Pop-Up Modal Overlay
Normally, pop-up modal windows have overlays with a transparent darker background that covers entire browser screen.
Define a div with an id model-overlay which will cover the entire screen.
<div id="modal-overlay">
<div>
Then, make it to full screen using height:100vh CSS property.
Bring it in front of the button by using position:absolute with a transparent background colour.
#modal-overlay {
width: 100%;
height: 100vh;
position: absolute;
background: rgba(0, 0, 0, 0.7);
}
I just added the border to see the boundaries of the modal-overlay element.
Center Pop-Up Modal Window To The Modal Overlay
Create a div with an id modal inside the modal-overlay element, which will be an actually pop-up modal window that user interacts with.
<div id="modal-overlay">
<div id="modal">
</div>
<div>
Add CSS style to make it visible on the screen.
Adding width:100% and max-width:650px will make sure the width of the pop-up modal window won’t exceed when the browser width is more than 650px.
If the browser width is less than 650px, the pop-up modal window will stretch the width to fill the screen which is normally for mobile viewports.
#modal-overlay #modal {
max-width: 650px;
width: 100%;
background: white;
height: 400px;
}
Centre the pop-up modal window to the screen using Flexbox.
To do that, just add the three lines of Flexbox code to the modal-overlay which are:
- display:flex → Convert an HTML element to Flexbox
- align-items:center → centre the pop-up modal window vertically to the viewport
- justify-content:center → centre the pop-up modal window horizontally to the viewport
#modal-overlay {
...
display: flex;
align-items: center;
justify-content: center;
}
Open Up Pop-Up Modal Window On Button Click
Now we have the basic pop-up modal window designed using CSS.
Make it visible when a user presses the open modal button.
To do that,
First, hide the modal overlay by default by changing its display property from flex to none.
#modal-overlay {
...
display: none; // Changed from flex to none
align-items: center;
justify-content: center;
}
Create a DOM reference to the open-modal button as well as the modal-overlay elements.
const openModalButton = document.getElementById("open-modal");
const modalWindowOverlay = document.getElementById("modal-overlay");
Attach a click event to the openModalButton with the callback arrow function showModalWindow.
const showModalWindow = () => {
modalWindowOverlay.style.display = 'flex';
}
openModalButton.addEventListener("click", showModalWindow);
Set the display property of the modalWindowOverlay to flex inside showModalWindow() function which will open up the modal window.
As you can see, there is no way we can close/hide the pop-up modal window after its became visible on the screen.
Let’s fix it!
Close/Hide Pop-Up Modal Window On Button Click
Typically, there will be a close button on the top or bottom right side of the pop-up modal window.
Let’s add a close button on the bottom left side of the modal window.
Define header, content and footer HTML elements inside the pop-up modal window.
<div id="modal">
<div class="modal-header">
<h2>Modal Pop Up Window</h2>
</div>
<div class="modal-content">
<p>Modal Content</p>
</div>
<div class="modal-footer">
<button id="close-modal">Close</button>
<button>Save</button>
</div>
</div>
Generally, you’ll have two buttons on the footer of the pop-up modal window, which may be save and close.
Let’s push the buttons to the bottom using Flexbox.
Turn the display property of the pop-up modal window to flex and set the flex direction to column.
Set margin-top to auto to the .modal-footer element which pushes the buttons to the bottom.
#modal-overlay #modal {
max-width: 650px;
width: 100%;
background: white;
height: 400px;
display: flex;
flex-direction: column;
padding:10px;
}
#modal-overlay #modal .modal-footer {
margin-top: auto;
}
Let’s hide the pop-up modal window when the user presses the close button.
Define a DOM reference of the close button.
Attach a click event to the close button with the call back function hideModalWindow.
Declare hideModalWindow function and set the display property of modalWindowOverlay to none inside it.
const closeModalButton = document.getElementById("close-modal");
const hideModalWindow = () => {
modalWindowOverlay.style.display = 'none';
}
closeModalButton.addEventListener("click", hideModalWindow);
Hide Pop-Up Modal Window When Modal Overlay Is Clicked
In addition to the close button, you often see the pop-up modal window will be closed or hidden when the user clicks away from it.
To do that, we need to identify if a user clicks the actual pop-up modal window and its content inside or the modal overlay that covers the entire screen.
To check that,
Attach a click event to the #modal-overlay with a callback function hideModalWindowOnBlur.
modalWindowOverlay.addEventListener("click", hideModalWindowOnBlur)
Using e.target and e.currentTarget properties of an event object we can identify where a user clicks when the pop-up modal window is visible on the screen.
e.target will capture a clicked HTML element which can be either the parent or child elements.
The parent element will be referred to an element that has a click event attached to.
In this case, the #modal-overlay.
The child elements will be referred to all the HTML elements right inside the parent element.
On the other hand, e.currentTarget will only get the parent element regardless of where user clicks either parent or child elements.
In this case the #modal-overlay.
This way we can determine whether a user clicks the #modal-overlay or the actual pop-up modal window.
If a user presses the modal overlay, hide/close it by checking if e.target value is equal to e.currentTarget.
const hideModalWindowOnBlur = (e) => {
if(e.target === e.currentTarget) {
hideModalWindow();
}
}
If you’ve any questions or suggestions about this article, feel free to reach out to me by commenting below and I’ll read and reply to each and every one of them.
I’m looking forward to hearing from you.
Happy coding…
Top comments (3)
You could also use the dialog element
Nice article as an exercise to touch to multiple concepts with both CSS and JavaScript.
I agree, the dialog option seems easier now that it is supported by browsers though.
For anyone reading that is interested in more details about this, I found this article from @dailydevtips1 great:
Trying out native dialog modals
Chris Bongers ・ Aug 8 ・ 3 min read
Also there is an accessibility issue that is easy to make: forget to capture the focus. When a modal is opened, we should not be able to focus elements that are outside the modal. I think your example has this problem.
Recently did for a small website, for New Year's discounts.
CSS
JS
```document.addEventListener("DOMContentLoaded", function() {
var popup = document.getElementById("popup");
var close = document.getElementsByClassName("close")[0];
});```
But as for me, it's easier to find a ready-made beautiful template, adapt it and put it on the site. It will take much less time. Here here took a template for myself claspo.io/ not a bad choice.