A guide to integrating Tailwind UI animations into pure HTML and JavaScript

I am struggling to implement the animation part of tailwindui.com components that I want to use. The instructions are provided in the comments, but I'm having trouble integrating them into my code. I prefer not to rely on any frameworks or libraries as I am working with plain HTML and JavaScript.

My current challenge involves showing/hiding a modal dialog. The animation for the background overlay is specified as:

 <!--
      Background overlay, show/hide based on modal state.

      Entering: "ease-out duration-300"
        From: "opacity-0"
        To: "opacity-100"
      Leaving: "ease-in duration-200"
        From: "opacity-100"
        To: "opacity-0"
    --> 

I need help incorporating this information into the background overlay div.

<div id="myModal" class="hidden fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
  <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    <!--
      Background overlay, show/hide based on modal state.

      Entering: "ease-out duration-300"
        From: "opacity-0"
        To: "opacity-100"
      Leaving: "ease-in duration-200"
        From: "opacity-100"
        To: "opacity-0"
    -->
    <div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"gt;</div>

Here's what I've attempted so far:

<style>
  .modalEntry {animation:modal-in 1s;}  
  .modalExit {animation:modal-in 1s;}

@keyframes modal-in {
    from {opacity-0;}
    to {opacity-100;}
}
@keyframes modal-out {
    from {opacity-100;}
    to {opacity-0;}
}
</style>

<button class="border border-red-500" onclick="toggleModal()">Toggle modal</button>

<div id="myModal" class="hidden fixed z-10 inset-0 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
  <div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
    <div class="fixed modalEntry inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>

    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>

    <div class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
      <div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
        <div class="sm:flex sm:items-start">
          <div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
            <svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
            </svg>
          </div>
          <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
            <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">Deactivate account</h3>
            <div class="mt-2">
              <p class="text-sm text-gray-500">Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.</p>
            </div>
          </div>
        </div>
      </div>
      <div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
        <button onclick="toggleModal()" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">Deactivate</button>
        <button onclick="toggleModal()" type="button" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">Cancel</button>
      </div>
    </div>
  </div>
</div>

<script>
  function toggleModal () {
        document.getElementById("myModal").classList.toggle("hidden");
  }
</script>

To test the code easily, I have created a CodePen link: https://codepen.io/rishavs/pen/BadMQaN?editors=1000

Answer №1

In my current project, I have integrated jQuery into an older PHP system, which might give you some insights.

To begin, assign an ID to "slide-over-title" and include suggested animations:

<div class="fixed inset-0 overflow-hidden z-[2000] bg-gray-200 transform transition ease-in-out duration-500 sm:duration-700 translate-x-full" aria-labelledby="slide-over-title" id="slide-over-title" role="dialog" aria-modal="true">

Then, develop a straightforward "toggle" function that can be utilized anywhere:

function toggleSlider() {
    if($("#slide-over-title").hasClass("translate-x-full")) {
    $("#slide-over-title").removeClass("translate-x-full");
    $("#slide-over-title").addClass("translate-x-0");
    } else  {
    $("#slide-over-title").addClass("translate-x-full");
    $("#slide-over-title").removeClass("translate-x-0");  
    }
}

While I'm using the Tailwind CDN in this example snippet, it's recommended to use the Tailwind preprocessor or CLI for generating optimized CSS files in production environments.

function toggleSlider() {
        if($("#slide-over-title").hasClass("translate-x-full")) {
        $("#slide-over-title").removeClass("translate-x-full");
        $("#slide-over-title").addClass("translate-x-0");
        } else  {
        $("#slide-over-title").addClass("translate-x-full");
        $("#slide-over-title").removeClass("translate-x-0");  
        }
    }
<button onclick="toggleSlider()">Toggle Slider</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<div class="fixed inset-0 overflow-hidden z-[2000] bg-gray-200 transform transition ease-in-out duration-500 sm:duration-700 translate-x-full" aria-labelledby="slide-over-title" id="slide-over-title" role="dialog" aria-modal="true">
  <div class="absolute inset-0 overflow-hidden">
    
    <div class="absolute inset-0" aria-hidden="true"></div>

    <div class="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 sm:pl-16">
      <!--
        Slide-over panel, show/hide based on slide-over state.

        Entering: "transform transition ease-in-out duration-500 sm:duration-700"
          From: "translate-x-full"
          To: "translate-x-0"
        Leaving: "transform transition ease-in-out duration-500 sm:duration-700"
          From: "translate-x-0"
          To: "translate-x-full"
      -->
      <div class="pointer-events-auto w-screen max-w-2xl">
        <div class="flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl">
          <div class="px-4 sm:px-6">
            <div class="flex items-start justify-between">
              <h2 class="text-lg font-medium text-gray-900" id="slide-over-title">Panel title</h2>
              <div class="ml-3 flex h-7 items-center">
                <button type="button" class="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" onclick="toggleSlider()">
                  <span class="sr-only">Close panel</span>
                  <!-- Heroicon name: outline/x -->
                  <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                  </svg>
                </button>
              </div>
            </div>
          </div>
          <div class="relative mt-6 flex-1 px-4 sm:px-6">
            <!-- Replace with your content -->
            <div class="absolute inset-0 px-4 sm:px-6">
              <div class="h-full border-2 border-dashed border-gray-200" aria-hidden="true"></div>
            </div>
            <!-- /End replace -->
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Answer №2

If you're looking for a simple way to add transition effects on Tailwind UI without relying on Vue/React, consider using Alpine.js. The documentation on docs explains how:

  <div
    x-show="isOpen"
    x-transition:enter="transition ease-out duration-100 transform"
    x-transition:enter-start="opacity-0 scale-95"
    x-transition:enter-end="opacity-100 scale-100"
    x-transition:leave="transition ease-in duration-75 transform"
    x-transition:leave-start="opacity-100 scale-100"
    x-transition:leave-end="opacity-0 scale-95"
    class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg"
  >

To implement this yourself, remember to change the display property first and then wait for a frame before applying the transition class. This step is crucial as switching from `display:none` to `display:block` won't trigger CSS transition animations. You can use `visibility` instead of `display`, but that might cause issues with clickable elements underneath. It's also important to hide the element after the transition completes to ensure the animation runs smoothly.

You can utilize `window.requestAnimationFrame()` or `setTimeout` methods to achieve this delay. If needed, there's a lightweight repository specifically designed for Tailwind UI transitions with Alpine.js called x-transition, which is approximately 1kb gzipped. However, considering Alpine.js offers additional functionality at around 7kb gzipped, it may be more efficient to directly use Alpine.js.

Whether DIY or through Alpine.js, don't forget to adhere to WAI ARIA practices while implementing these transitions.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Make the jQuery toggle() function work like a regular radio button when selecting multiple options at a time

I have recently created two radio buttons using <i> font icons. Previously, I had successfully used the same code to create a checkbox, so I applied it to the radio buttons as well. After fixing the positioning, everything seemed fine when interactin ...

Receive the innerHTML of an Element after appending additional Elements - Selenium

When working with my table in HTML, I have noticed that the <td> tag can be accessed in two different ways: 1. <td><font size="4" face="Arial"><i>Google</i></font></td> 2. <td>Google</td> I am curr ...

Using PHPMailer to send attachments uploaded through a form

I have a HTML form where users can select an attachment file (such as a PDF) and I want to send that file via email to a specified destination. While I am able to successfully send all other inputs through email, I'm having trouble with the attachmen ...

Are the menubar menus positioned beneath a different div element?

Currently facing an issue with an HTML Menubar where the menus are appearing below another div, and not getting displayed as expected: ...

HTML5 input type Color displays individual RGB values

This code snippet opens up a variety of options for the user to manipulate different color values such as R, G, B, HEX VALUE, HUE, etc. However, the specific requirement is to only extract the Red value. <input id="color_pick"type="color" value="#ff0 ...

What is the reason for not being able to align breadcrumb text to the right

This section contains HTML code and CSS for a breadcrumb container. The issue is that the breadcrumb is currently displayed on the left side. How can the breadcrumb be right-aligned? .breadcrumb-container { font-family: "Work Sans", sans-serif; ...

Tips for keeping a video background stationary while allowing the text to move smoothly

When I added the video for the background, it only appears at the top of the page. However, I want it to be visible as the rest of the page is scrolled. <div class="hero"> <video autoplay loop muted plays-inline class="back-video&qu ...

How can one transform a web-based application into a seamless full-screen desktop experience on a Mac?

"Which software can be utilized to enable a web application to display an icon on the desktop of a Mac computer, while also opening up the web application in a fully immersive full-screen mode that supports all the touch and gesture functionalities provi ...

How can I delete an individual HTML element that does not have a class or ID?

I am currently working with a theme that cannot be altered due to automatic update requirements. The theme includes the following HTML code snippet: <div class="dropdown-menu"> <a href="#">Profile</a> | <a href="#">Logout</a> ...

Is it possible to generate an image from HTML using PHP?

Can anyone suggest a way to generate an image from pure HTML using PHP, possibly utilizing the GD library or other similar tools? I am looking to display icons from external sites and considering if creating an image would help improve load times. If not ...

Issue with Bootstrap 4 navbar z-index not functioning as expected

Hello, I am struggling to place my navbar on top of an image using bootstrap 4. I have set the CSS properties for both elements, but it doesn't seem to be working. Here is the code I am using: <header> <nav class="navbar navbar-toggl ...

Changing between two images using HTML and CSS

I am currently designing a WordPress theme and I would like to create an effect where two different thumbnail images switch on hover. The code that I have come up with so far looks something like this : <a class="thumb" href="posturl"> <img src= ...

Is there a way to implement a scrollbar that only scrolls through one specific column in an HTML table?

I need help adding a scrollbar to a specific column in an HTML table. Take a look at this scenario https://jsfiddle.net/6wpdc4tL/: https://i.stack.imgur.com/svzIg.png This table should have two scrollbars, one for the light blue SCROLL column and another ...

Trouble with parseJSON when handling form POST in Python

I'm struggling with a javascript HTML page that has an action POST to a python file, expecting a JSON response back. Despite my efforts, I can't figure out how to catch and parse the JSON data. The HTML and python code excerpts below should show ...

Enhancing button images with gradient effects on hover

I'm currently working on adding a color gradient effect to a PNG graphic used as a button. I specifically want the color gradient to appear only when the user hovers over the image, and not just for background images like most solutions seem to provid ...

Position various images at specific coordinates on the screen using CSS

Looking for help with positioning four images on the screen using coordinates specified in the code. The top-left coordinate positioning is not displaying properly as intended. Can you assist in identifying and correcting the error? <!DOCTYPE html&g ...

The bullets in the HTML unordered list are partially hidden from view

My unordered list is experiencing issues with displaying bullets correctly. In Firefox and Internet Explorer, the bullets are only partially shown, while in Chrome they are not visible at all. Adding margin-left: 5px to the <li> element resolves this ...

Is there a way to organize a specific column based on user selection from a drop down menu on the client side?

When selecting Timestamp from the drop-down menu, I expect the TimeStamp to be sorted in either ascending or descending order. Similarly, if I choose Host, the Host should be sorted accordingly. Despite using the Tablesorter plugin, sorting doesn't s ...

The functionality of multiple UI-Views is not meeting the intended outcomes

I'm facing an issue with integrating multiple UI-views in my AngularJS dashboard app. Despite following the directory structure, I am unable to get it working as expected. This is how my directories are organized: index.html app/ app.js dash ...

Can you explain what is meant by an "out of DOM" element?

I'm feeling a bit lost when it comes to DOM nodes and all the terminology surrounding them. Initially, I believed that the DOM consisted solely of what I could see in my inspector - nothing more, nothing less. However, I've come across functions ...