Creating modal windows with Alpine.js and HTMX

Creating a modal window is a pretty common task when building a new website but sometimes it is not obvious how to do it by just using HTMX and Alpine.js. Both libraries are going to be complementary in building a proper modal window experience.

  • calendar_month 4.1.2024
  • pace 10 minutes

In the example below, we are going to build a modal window that will be opened by clicking on a link. The content will be loaded into a modal window. To dismiss the window user has to click outside of the modal window or hit the escape button. One additional feature that we will add is the possibility to share a link after opening a modal window.

Responsibilities of HTMX and Alpine.js libraries

  • HTMX will load content from an external URL and it will change the URL link
  • Alpine.js will take care of opening/closing the modal window and it will reset the URL

Base template for the link and modal window

Let's start with the basic skeleton of our modal window experience. On the body element, we will specify several attributes for Alpine.js. x-data attribute is responsible for declaring a new variable in Alpine.js called openModal which holds a flag if the modal window is open or not. x-bind:class is chanding CSS classes on body element based on openModal variable. In the example below it will add overflow-hidden CSS class when the modal window is open.

In the post example, Tailwind classes are used to style the components. The overflow-hidden class on body element hides the main content scrollbar so it will be not possible to scroll the main content area. Later we will add a scrollbar on the modal window which allows to scroll modal's content.

<body x-data="{openModal: false}"
      x-bind:class="openModal && 'overflow-hidden'">

    <!-- Link template here-->

    <!-- Modal template here -->

    <!-- Don't forget to load libraries -->
    <script defer src="/js/htmx.js"></script>
    <script defer src="/js/alpine.js"></script>

Modal window

The most important part of the implementation is the modal window below. It consists of three important parts. The main container has x-show attribute for controlling when the modal window is open or closed. The x-on action will close the modal window once the escape button is hit and it will change the URL.

The background overlay is a straightforward HTML element. It adds a layer below a modal window covering the main content. The example below has a dark background with some opacity so the content below is barely visible.

The main component in the example is the modal window itself. It has a fixed position and overflow-auto CSS class which is for adding a scrollbar when the modal's content is larger than the window's height. There is x-on:click.outside attribute which will close the modal. The div element with id modal-content is the wrapper where the content is going to be loaded.

<div x-show="openModal"
     x-on:keydown.escape.window="openModal = false; history.pushState({}, '', '/')">

    <!-- Background overlay -->
    <div class="bg-slate-900/80 bottom-0 fixed left-0 right-0 top-0 z-20"></div>

    <!-- Modal window styling-->
    <div class="fixed bottom-0 p-6 left-0 overflow-auto right-0 top-0 z-30 lg:py-24">
        <div class="container max-w-7xl mx-auto relative shadow-lg z-90"
             x-on:click.outside="openModal = false; history.pushState({}, '', '/')">
            <!-- Main content from HTMX will be inserted here-->
            <div id="modal-content" class="bg-white p-6 rounded-lg lg:p-12"></div>

Link with Alpine.js and HTMX triggers

Let's create a basic link pointing at the URL with the desired content. Below you can find an example HTML which can be copied and pasted inside the codebase. Of course, links have to be changed. The code below will create a basic hyperlink. When the user clicks on it, the target URL with queried, and HTMX will find post-content element which will be put into modal-content. After that, Alpine.js will be informed that a modal window can be opened.

<a href="/some-content"
   x-on:htmx:after-on-load="openModal = true">
    Link pointing at the content

It is important to not forget to create under /some-content URL a div element with id post-content. This element will be used by HTMX to load just a part of the response into the modal window instead of the whole response.

Detailed description of Alpine.js and HTMX attributes

  • href contains a link pointing at the content that we want to fetch
  • hx-get tells HTMX to trigger GET query
  • hx-select will choose an HTML element from the response
  • hx-target where the content is going to be appended
  • hx-push-url changes the current URL so it will be possible to share it
  • x-on:htmx:after-on-load Alpine.js event triggered when HTMX event is finished

Let's work together

Did you decide to start using Unfold in your application but you need help with integration? Feel free to get in touch for consulting or development services.

  • verified Save time and focus on what matters: building product
  • verified Get instant access to the know-how pool and experience
  • verified Supercharge your development processes and quality of application
  • verified Incorporate custom Django applications into Unfold

* The cost of service starts from €329 EUR.

© 2024 Created by All rights reserved.