What is causing the lack of animation when the drawer is closing?

I am looking to create an animated drawer that slides in and out. When the animation finishes, I want it to disappear by setting `display: none`, but if the drawer is closed without animating out, it should just vanish.

const Drawer = ({ closeDrawer, isDrawerOpen }) => {
  const [isAnimating, setIsAnimating] = useState()
  let drawerClassName
  if (isDrawerOpen) {
    drawerClassName = "drawer-in"
  } else if (!isDrawerOpen && isAnimating) {
    drawerClassName = "drawer-animating"
  } else if (!isDrawerOpen && !isAnimating) {
    drawerClassName = "drawer-out"
  }
  return (
    <>
      <div
        className={`drawer ${drawerClassName}`}
        onAnimationStart={() => setIsAnimating(true)}
        onAnimationEnd={() => setIsAnimating(false)}
      ></div>
      <div onClick={closeDrawer}></div>
    </>
  )
}

CSS:

.drawer {
  height: 100%;
  width: 60%;
  background-color: #fff;
  position: absolute;
  right: 0;
  top: 0;
  opacity: 1;
  z-index: 3;
  transform: translateX(100%);
}

.drawer-in {
  animation: 0.7s drawerIn;
  transform: translateX(0);
  display: block;
}

.drawer-animating {
  animation: 0.7s drawerOut;
  display: block;
}

.drawer-out {
  animation: 0.7s drawerOut;
  display: none;
}

@keyframes drawerIn {
  0% {
    transform: translateX(100%);
  }
  1% {
    transform: translateX(100%);
  }
  100% {
    transform: translateX(0);
  }
}

@keyframes drawerOut {
  0% {
    transform: translateX(0);
  }
  99% {
    transform: translateX(100%);
  }
  100% {
    transform: translateX(100%);
  }
}

Answer №1

The reason behind this behavior is that when you apply the drawer-out class to an element, the display: none; property takes effect immediately, causing the animation to be invisible.
One way to tackle this issue is by using a setTimeout function in your JavaScript code to wait for the animation to finish before changing the display property to none. This approach ensures that the 'closing animation' completes before removing the element. Check out the example below for implementation details.

In essence, the provided snippet triggers the closing animation by adding a corresponding class with the animation effect. Subsequently, a timeout function is set to synchronize with the CSS animation duration (specified in milliseconds). Once the timeout expires, the animation class is removed, and the data attribute of the element switches to closed, hence triggering the display none effect. I hope this clarifies things for you.

const menu = document.querySelector('.menu');
const menuToggle = document.querySelector('.menu_toggle');
menuToggle.checked=false

menuToggle.addEventListener('change',(e)=>{
    menuToggle.disabled=true
    let menuState = menu.dataset.menuState
    if(menuState==='closed'){
        menu.dataset.menuState='opened'
        setTimeout(() => {
            menuToggle.disabled=false
        }, 500);
    }else{
        menu.classList.add('animate_close')
        setTimeout(() => {
            menu.classList.remove('animate_close')
            menu.dataset.menuState='closed'
            menuToggle.disabled=false
        }, 500);
    }
})
body {
    background-color: rgb(235, 235, 235);
}

.menu {
    background-color: black;
    color: white;
    width: fit-content;
}
.menu {
    transition: all .5s ease-in-out;
}

.menu[data-menu-state="closed"] {
    background-color: red;
    display: none;
}
.menu[data-menu-state="opened"] {
    animation: openMenu .5s ease-in-out;
    transform: translateX(100%);
    background-color: green;
}
.menu.animate_close{
    background-color: rgb(0, 30, 128);
    animation: closeMenu .5s ease-in-out;
    opacity: 0;
}

@keyframes openMenu {
    0% {
        transform: translateX(0);
    }

    100% {
        transform: translateX(100%);
    }
}

@keyframes closeMenu {
    0% {
        transform: translateX(100%);
    }
    100% {
        transform: translateX(0);
      
    }
}
<body>
    <label for="menu_toggle">Menu Toggle</label>
    <input id="menu_toggle" type="checkbox" class="menu_toggle">
    <div class="menu_container">
        <div class="menu" data-menu-state="closed">
            <ul>
                <li>Item1</li>
                <li>Item2</li>
                <li>Item3</li>
            </ul>
        </div>
        
    </div>
   
    <script src="main.js"></script>
</body>

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

Various Plus/Minus Containers

One issue I am facing is that when using multiple counters on the same page, my - and + buttons to decrease or increase the number in a text box do not function properly. The script provided below works for one counter. How can I modify this code so that ...

CSS tabs are not functioning properly as hyperlinks

Having some trouble with this website: The tabs on the site are not functioning when clicked. I've implemented a hover effect using CSS, but I'm unable to get the tabs to work properly. Please advise. Thank you. ...

Utilizing the power of Material-UI with React in conjunction with Python-Django: A comprehensive

I am seeking guidance on implementing React with Material UI components in my web application. The technologies I have utilized in multiple projects include: Materialize CSS, Javascript, Jquery. The technologies I wish to explore for future projects are ...

Issue with Node.js MongoDB collection.find().toArray not returning results

Despite coming across questions similar to mine, I struggled to resolve the issue independently. Within my '../models/user' model, my goal is to retrieve all users and store them in an array, which will then be returned to the controller for fur ...

"Utilize JavaScript to detect both the loading and unloading events on a webpage

I attempted to capture the window.open onload and onunload events. The issue arises when I use URLs from other domains. For example: When the URL is for the same page, both events trigger as desired. window.open("/") View PLUNKER with same page URL .. ...

Discover the best practices for integrating @react-native-community/datetimepicker with React Hook Form!

I am attempting to create a date picker that appears when a field with an icon and the current date in string format is clicked. I am using React Native, React Hook Form, and @react-native-community/datetimepicker. Fortunately, I came across an interesti ...

Execute multiple JavaScript files dynamically by utilizing the same npm run command

My directory structure: app Model user.js post.js Contents of my package.json file: "scripts": { "migrate": "node ./app/Model/" } I am looking to execute JavaScript files via command line in a dynamic manner. For example: npm run migr ...

increase the variable based on the count of clicks

I need some assistance with the code snippet below: Javascript: var counter = 0; var totalItems = 8; var remainingItems = $num - totalItems; if (remainingItems == 22) { $('#next').click(function(e) { e.preventDefault(); cou ...

Using ternary operators and filters in a binding with AngularJS

I currently have a basic data binding setup: {{ myAccount.Balance }} Then I decided to incorporate a couple of filters: {{ myAccount.Balance | filter1 | filter2 }} Nevertheless, I am interested in using a ternary operator for scenarios where the Balanc ...

Ways to guarantee the protection of APIs that are accessible to both front-end applications and other servers

In the process of creating a website, I am faced with the challenge of enabling the front-end page to communicate with the server using AJAX for data retrieval and posting. The same APIs offered by the server are also utilized by private apps within the ...

I need to extract information from the database and save all entries from the form in order to send them to myself. This includes calculating the real-time multiplication of weight and pieces

For a project, I need to gather contact data from the client, and then populate a MySQL database with the information to create new rows in a table. There's an additional requirement where I have to calculate the total weight of element pieces multip ...

Tips on transferring information from a component to an instance in Vue

My goal is to retrieve data from a component and transfer it to a variable within my root Vue instance. Vue Instance Configuration: new Vue({ el: '#root', data: { searchResultObject: '' }, methods: { // ...

Is there a way to make my DIVS update their content dynamically like buttons do, without manually adding an onclick function in the HTML code?

I am currently customizing a WordPress theme that lacks the option for onclick events on div elements. However, I can assign classes and IDs to them. In my design, I have four spans in a row, and when each span is clicked, I intend for the corresponding p ...

Error: The configuration property is not defined, causing a TypeError at Class.run ~/node_modules/angular-cli/tasks/serve.js on line 22

I'm encountering a persistent error on my production server that indicates a missing angular.json file, even though the file is present in the root of my project! Every time I run npm start, npm build, or npm test, I receive the same error message. ...

Guide: How to include a date value within a JSON format? [See code snippet below]

Currently, I am developing a react application that includes a form with sections for basic details and employment information. The form is almost completed, and I have successfully structured the data in JSON format for different sections. To see a work ...

Encountering an error in Express while attempting to upload an image due to the inability to read the property 'file' of undefined

I am currently learning Express framework. I encountered an error while trying to upload an image using Express. The error message I received is "Cannot read property 'file' of undefined." Below are the code snippets that I am using, and I&apo ...

`On mouseup event, changing specific text`

I've been working on a real-time HTML highlighter that surrounds selected text with span elements containing a background property. Check out the fiddle here: https://jsfiddle.net/4hd2vrex/ The issue arises when users make multiple selections, leadi ...

Improving conditional rendering in Mui <Cards> component by fixing state behavior

I have a situation where I want to display a Floating Action Button inside each Mui card when hovered over. However, I'm running into an issue with the hover state affecting all cards instead of just the one being interacted with. How can I ensure tha ...

Sending information from a rails controller to a react component

Wondering how to pass the example @post = Post.all from the controller to React component props while integrating Rails with React via Webpacker. Is it necessary to do this through an API or is there another way? ...

Using a checkbox to enlarge a table

<script type='text/javascript' src='http://code.jquery.com/jquery-1.4.2.js'></script> <script type='text/javascript'> $(window).load(function () { $('.varx').click(function () { ...