Transition duration is not applying correctly with VanillaJS

Viewed 503

I'm using the slide-overs from TailwindUI with vanilla JS and the overlay and opacity apply correctly, but the animation is happening instantly instead of using the duration class.

https://tailwindui.com/components/application-ui/overlays/slide-overs

Here is the HTML snippet for the overlay component.

  <div class="hidden fixed inset-0 overflow-hidden" id="panel-container">
    <div class="absolute inset-0 overflow-hidden">
      <!--
        Background overlay, show/hide based on slide-over state.
  
        Entering: "ease-in-out duration-500"
          From: "opacity-0"
          To: "opacity-100"
        Leaving: "ease-in-out duration-500"
          From: "opacity-100"
          To: "opacity-0"
      -->
      <div class="transition-opacity ease-in-out duration-1000 opacity-100 absolute inset-0 bg-gray-600 bg-opacity-70" id="panel-overlay" aria-hidden="true"></div>
      <section class="absolute inset-y-0 right-0 max-w-full flex" aria-labelledby="slide-over-heading">
      </section>
    </div>
  </div>

... and here is the script that removes the hidden class on the panel-container div.

    const panelContainer = document.querySelector('#panel-container');

    document.querySelector('#panel-settings--open').addEventListener('click', function(event) {
      event.preventDefault();
      
      panelContainer.classList.toggle('hidden');

    });

Can anyone point me into the right direction of what I'm doing wrong here?

1 Answers

I was having a very similar issue with transitions so I want to share how I fixed it. Note that this may require Tailwind v3 (v2 in CodePen was not working for me).

First off, in the OP's code I just see the hiding/showing of the main Div. We also need some JS code to add the appropriate CSS class(es) for the transitions on the appropriate elements. HOWEVER: applying CSS transitions right after showing an element (i.e. removing "display: none") does not work! See official note from Mozilla here. I got stuck for a long time trying to figure out this single issue.

I fixed my problem using Mozilla's recommendation of applying a setTimeout() with a few milliseconds before applying the CSS properties. In the OP's case, something like this should work (UNTESTED):

const panelContainer = document.querySelector('#panel-container');
document.querySelector('#panel-settings--open').addEventListener('click', function(event) {
  event.preventDefault();

  panelContainer.classList.remove('hidden');
  setTimeout(function(){
    document.getElementById('panel-overlay').classList.add("ease-in-out", "duration-500", "opacity-100");
  }, 10);
});

The above is for showing the slide-over and assumes the panel-overlay element does not already have the transition-related CSS classes (or at least, not the one for opacity).

To hide the slide-over and make the transitions work correctly is a bit trickier. You'll need to apply the appropriate classes (e.g. opacity-0) and let the transition finish before applying the hidden class to the main Div. For this, I added an event listener for the "transitionend" event and applied hidden once that ran.

Related