[Javascript] Implementing Modal Boxes with minimal code

modal box



In this article, we will demonstrate how to implement Modal Boxes with minimal code.
By utilizing the dialog element introduced with HTML5, you can significantly reduce the effort.





⓪Requirements

In this article, we aim to implement modal boxes with minimal code, but we do not intend to compromise on functionality.
We plan to meet the following requirements typically expected of modal boxes.

  • Close the modal when the close button is clicked.
  • Close the modal when the background is clicked.
  • Disable scrolling on the body while the modal is open.
  • Make elements outside the modal unfocusable when the modal is open.
  • Ensure smooth functionality even with multiple instances of the modal.



From this point, we will provide a detailed explanation step by step. However, if you prefer not to have explanations and would like to see the complete source code, you can skip directly to the full source code from here.





①Prepare the modal parts using the <dialog> element

The <dialog> element was introduced in HTML5. Since it provides the visual aspects of modal boxes, you can significantly reduce the need for CSS (though JavaScript is still required).
It’s also beneficial that it makes elements outside the modal unfocusable when the modal is open.


The <dialog> element is very straightforward. You just need to wrap the content you want to display in the modal with <dialog></dialog>.
Let’s also prepare a button that will act as the trigger to open the modal.

<button>Open the modal box</button>
<dialog>
    <img src="./img/sample.png">
</dialog>


It appears that the <dialog> element is already supported in major web browsers.
Reference: https://caniuse.com/?search=dialog





②Open the Modal Box

Let’s implement the process to open the modal box.
By using JavaScript and executing the showModal method on the <dialog> element, the modal box will open.


In the HTML part, we will make the button to call the openModal function (will be defined later) when clicked.
By specifying this as an argument, you can pass the button itself to the function when it is clicked.

<button onclick="openModal(this)">Open the modal box</button> <!-- modified -->
<dialog>
    <img src="./img/sample.png">
</dialog>


In the JavaScript part, we define the openModal function.
It’s a simple function that executes the showModal method on the adjacent element to the received element.

const openModal = (elem) => 
    elem.nextElementSibling.showModal()





③Set up the close button

The <dialog> element does not come with a built-in close button, so you need to set it up yourself.
You can close the modal box by executing the close method on the <dialog> element using JavaScript.


In the HTML, place the close button as follows.
Make sure to set it up to call the closeModal method (will be defined later) when clicked.

<button onclick="openModal(this)">Open the modal box</button>
<dialog>
    <div onclick="closeModal(this)" class="cloase-btn">x</div>  <!-- added -->
    <img src="./img/sample.png">
</dialog>


In the CSS, define the style of the close button as follows.
Here, we position it as an ‘X’ mark in the top right corner.

dialog .cloase-btn {
    position: absolute;
    cursor: pointer;
    top: 6px;
    right: 6px;
    font-size: 36px;
    line-height: 0.6;
}


In the JavaScript, define the closeModal function.
It’s a simple function that executes the close method on the <dialog> element which contains the received element.

const closeModal = (elem) =>
    elem.closest('dialog').close()



We put demo up to this point. It currently fulfills 3 out of 5 requirements.

  • Close the modal when the close button is clicked.
  • Close the modal when the background is clicked.
  • Disable scrolling on the body while the modal is open.
  • Make elements outside the modal unfocusable when the modal is open.
  • Ensure smooth functionality even with multiple instances of the modal.
x
sample image
x
sample image





④Close the modal when the background is clicked

To make it more convenient, let’s allow closing the modal by clicking on the background.

We will modify it to call the previously defined closeModal method when the <dialog> element is clicked.

<button onclick="openModal(this)">Open the modal box</button>
<dialog onclick="closeModal(this)"> <!-- modified -->
    <div onclick="closeModal(this)" class="cloase-btn">x</div>
    <img src="./img/sample.png">
</dialog>


With this change, clicking on the background will close the modal, but there’s one issue.
The issue is that clicking on the content part also closes the modal box.
Let’s improve this behavior.


We will modify the HTML as follows to pass an event to closeModal method.
Please note that this is done to detect content clicks in JavaScript, and the argument name must be “event“.

<button onclick="openModal(this)">Open the modal box</button>
<dialog onclick="closeModal(this, event)">                              <!-- modified -->
    <div onclick="closeModal(this, event)" class="cloase-btn">x</div>   <!-- modified -->
    <img src="./img/sample.png">
</dialog>


Modify the JavaScript as follows to execute the closing process only when the click event occurs outside the content.

const closeModal = (elem, event) => elem == event.target &&     //modified
    elem.closest('dialog').close()


For those who find the above condition confusing, here’s an additional explanation:

The elem variable contains the element that invoked closeModal, and event.target contains the element that was actually clicked.
Therefore, when the content is clicked, the condition evaluates to dialog element == content, which results in false, and the closing process is not executed.





We put demo up to this point. It currently fulfills 4 out of 5 requirements.

  • Close the modal when the close button is clicked.
  • Close the modal when the background is clicked.
  • Disable scrolling on the body while the modal is open.
  • Make elements outside the modal unfocusable when the modal is open.
  • Ensure smooth functionality even with multiple instances of the modal.


x
sample image
x
sample image







⑤Prevent scrolling of the body when the modal is open

Currently, even when the modal box is open, you can still scroll the background body. So let’s improve this.

We can achieve this by setting the overflow property of the body element to “hidden” when the modal box is open, and remove it when the modal is closed.

const openModal = (elem) => 
    [document.body.style.overflow="hidden", elem.nextElementSibling.showModal()]    //modified

const closeModal = (elem, event) => elem == event.target &&
    [document.body.style.overflow="initial", elem.closest('dialog').close()]        //modified



We put demo up to this point. It now meets all of the specified requirements.

  • Close the modal when the close button is clicked.
  • Close the modal when the background is clicked.
  • Disable scrolling on the body while the modal is open.
  • Make elements outside the modal unfocusable when the modal is open.
  • Ensure smooth functionality even with multiple instances of the modal.
x
sample image
x
sample image






⑥About the style of the <dialog> element

The <dialog> element comes with default styling to give it the appearance of modal boxes.
However, there may be cases where you want to customize things like the background color.
Let’s conclude by discussing the styling options for the <dialog> element.

Background color

dialog::backdrop {
    background: #1119;
}


Border and spacing

The default borders and spacing are defined for the <dialog> element, so you can reset them if they are not needed.

dialog {
    padding: 0;
    border: 0;
}






The full text of source code

In the end, I put the full text of source code.

<style>
    dialog {
        padding: 0;
        border: 0;
    }
    dialog::backdrop {
        background: #1119;
    }
    dialog .cloase-btn {
        position: absolute;
        cursor: pointer;
        top: 6px;
        right: 6px;
        font-size: 36px;
        line-height: 0.6;
    }
</style>

<button onclick="openModal(this)">Open the modal box</button>
<dialog onclick="closeModal(this, event)">
    <div onclick="closeModal(this, event)" class="cloase-btn">x</div>
    <img src="./img/sample6.png">
</dialog>

<script>
    const openModal = (elem) => 
        [document.body.style.overflow="hidden", elem.nextElementSibling.showModal()]

    const closeModal = (elem, event) => elem == event.target &&
        [document.body.style.overflow="initial", elem.closest('dialog').close()]
</script>








That is all, it was about how to implement Modal Boxes with minimal code.

Sponsored Link

You can subscribe by SNS

Sponcerd Link