What is the best way to smoothly transition an element into view, then make it disappear seamlessly by fading it

Issue

My current code features a <button> that, upon a single click, updates the class of a <div> element to "fade-in" and inserts it into the DOM. This action causes the <div> to visually fade in once it's in the DOM. However, if I click the button twice rapidly while the <div> is already present in the DOM, the element fades out and in before being removed.

Desired Outcome

My goal is for the <div> to fade out and be removed from the DOM with the initial click, and then fade in and be reinserted into the DOM with the second click. I want the visual effects to align with the DOM manipulation and prevent the fade-out and fade-in confusion caused by rapid clicking.

Resolution Approach

To address this issue, I have made multiple attempts with Promises, but unfortunately, none have been successful. As I am relatively new to JavaScript, I am uncertain whether my use of Promises is incorrect or if there are flaws in my overall approach. Any guidance or assistance would be greatly appreciated.

Answer №1

I have acknowledged @nem0z's response and also wanted to contribute an extended solution in response to my query below his answer (regarding how to modify the animation while it is still in progress). The solution involves utilizing the clearTimeout() function to prevent the execution of the code within the setTimeout().

const container = document.createElement("div");

let toggled = false;
let activeAnimation = false;

const button = document.querySelector("button");
button.addEventListener("click", event => {
  if (activeAnimation) {
    clearTimeout(timeoutID);
  }
  toggled = !toggled;
  activeAnimation = true;
  if (toggled) {
    container.setAttribute("class", "fade-in");
    button.parentElement.insertBefore(container, button.nextSibling);
    timeoutID = setTimeout(() => {
      activeAnimation = false;
    }, 500)
  } else {
    container.setAttribute("class", "fade-out");
    timeoutID = setTimeout(() => {
      container.remove();
      activeAnimation = false;
    }, 500)
  }
})
div {
    width: 100px;
    height: 100px;
    background-color: black;
}

.fade-in {
    animation: fade-in 500ms linear;
}

@keyframes fade-in {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

.fade-out {
    animation: fade-out 500ms linear;
}

@keyframes fade-out {
    0% {
        opacity: 1;
    }
    
    100% {
        opacity: 0;
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8>
    <meta http-equiv="X-UA-Compatible" content="IE-edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="../../CSS/Test.css">
    <script src="../../JS/Test.js" async></script>
    <title>Document</title>
</head>
<body>
    <button> Fade In / Fade Out </button>
</body>
</body>
</html>

Answer №2

In my code, I utilize a variable called inAnimation which is initially set to true when an animation is triggered, and then set to false at the completion of the animation utilizing setTimeout(f, animationDuration):

To make the issue more visible, I have set the animation duration to 1000ms.

Here is the part of the code that needs to be changed:

const container = document.createElement("div");

let toggled = false;
let inAnimation = false; // is div currently animated

const button = document.querySelector("button");
button.addEventListener("click", event => {
    if(inAnimation) return; // check if there is an ongoing animation

  if (!toggled) { 

    inAnimation = true;
    container.setAttribute("class", "fade-in");
    
    button.parentElement.insertBefore(container, button.nextSibling);
    setTimeout(() => {
        inAnimation = false; // marks end of animation
    }, 1000)

  } else if(!inAnimation) {
    inAnimation = true;
    container.setAttribute("class", "fade-out");

    setTimeout(() => {
        inAnimation = false; // marks end of animation
        container.remove();
    }, 1000)
  }

  toggled = !toggled; 
})
div {
    width: 100px;
    height: 100px;
    background-color: black;
}

.fade-in {
    animation: fade-in 1000ms linear;
}

@keyframes fade-in {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

.fade-out {
    animation: fade-out 1000ms linear;
}

@keyframes fade-out {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="../../CSS/Test.css">
    <script src="../../JS/Test.js" async></script>
    <title>Document</title>
</head>
<body>
    <button> Fade In / Fade Out </button>
</body>
</body>
</html>

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

Tips on how to connect with ngFor

I have been working on an application to display various events, but I am encountering an issue. Whenever I load the webpage, it appears empty and the console throws an error saying 'Can't bind to 'ngForEvent' since it isn't a know ...

Guide on changing JSON to HTML with a Groovy script

Looking to convert JSON to HTML using Groovy instead of Python due to running in Jenkins. Need help with Groovy code for the conversion. The JSON data : [ { "kubernetes.pod.name": "sds-endpoints-6-hn0fe2l", "container.id": "d19e001824978", "m ...

Rearranging the layout of elements: CSS switches up the text and button,

Having an issue. I created a background image with gradient colors for my web project and clipped it. Within this element, there is text and a button that I want to be centered inside the element - with the text above and the button below. Initially, ever ...

Attempting to send a formik form to a specified action URL

Seeking assistance with a simple fix as I navigate through the learning process. I have created an action called addTenant() that is supposed to receive the state and use it to dispatch a post API call, like so: export const addTenant = (tenant) => (di ...

Retrieve an image from an external web service and transfer it to a different route in Express.js

I am facing an issue with passing an image object from an external web service through a node express route. The specific problem I am encountering involves retrieving an image from a URL and attempting to pass it as is, but it seems to be not functioning ...

The Bootstrap carousel feature allows you to track the duration each image is displayed

Is there a way to track the amount of time a specific image is visible to the user in a Bootstrap 5 carousel? I'm interested in measuring how long a user views a particular image, such as a product image, in the carousel. For example, I'm lookin ...

Can we stub these types of functions in any manner?

One file named helperFunction.js contains the following code: module.exports = (arg1, arg2) => { \\function body } To use this function in another file named file.js, you can simply call it like this: let helperFunction = require(' ...

The Battle of Extends and Intersection in Typescript

Typescript's concept of extension is akin to C++'s inheritance. Intersection in Typescript involves creating a new object with all the properties from the intersected classes. Why utilize intersection when extends keyword can already merge ...

Can a horizontal navigation bar be designed to span the full width of the page without relying on a table?

I'm trying to create a horizontal navigation menu with variable width buttons that spans the full width of the containing div. I was successful in achieving this by using a table, as demonstrated in this example. The table cells adjust their size base ...

Issue with Jquery AJAX success function specifically in Firefox browser, while other functions in the script are functioning correctly

I have 4 scripts using ajax, but one of them isn't functioning properly in Firefox. Even the alert in success doesn't trigger anything. There are no error messages, just nothing happening. However, it works perfectly fine in IE and Chrome. Belo ...

Tabulator: the process of loading an extensive amount of data requires a significant amount of time

Currently, I am encountering an issue with loading data using a tabulator on my webpage. There are 38 tables that need to be populated, each containing approximately 2000 rows of data. The problem lies in the fact that it is taking an excessive amount of t ...

Why are my styles not working when referenced from the .module.scss file?

Here is the code snippet from my Sublayout.module.scss file: .pl-6 { padding-left: 6rem !important; } .pr-6 { padding-right: 6rem !important; } .pl-12 { padding-left: 12rem !important; } .pr-12 { padding-right: 12rem !important; } After im ...

We regret to inform you that the request cannot be processed by our Express

Currently, I am in the process of learning nodejs and expressjs and attempting to integrate it into the Spring MVC pattern. My intention behind this is to maintain cohesion within my files. However, the results are not quite aligning with my expectations.. ...

What are some strategies for improving the speed and efficiency of traversing an XML file with AJAX?

I am currently working with an XML file structured like this: <UUT> <DKBFile>091750</DKBFile> <part> <name>FL_U1</name> <xcoord>439</xcoord> <ycoord>132</ycoord> <width>55</width ...

Issue with scrollspy causing navigation items to not highlight correctly

If you want to track my progress, you can view it here - . Although clicking on the links in the navigation bar scrolls the page to the correct location, the link itself is not being highlighted. To address this, I had to incorporate an offset. var offset ...

Obtain an oAuth token through the use of npm

Recently, I've been working on a nodeJS service to fetch an OAuth token from a server. Unfortunately, I keep encountering errors when running the function below: var express = require('express') var http = require('http'); var htt ...

Can a PHP function be invoked in an URL using ajax?

I have created a PHP code with a single function that includes an output statement and I want to invoke that function as a URL within an AJAX script. I attempted to do this. <html> <head> <title>PHP Function Example</tit ...

Is it possible to invoke an AngularJs service by clicking a button?

Recently, I've been working on some AngularJS code involving a service and controller. angular.module('myModule', []).service("AttendanceService", function ($http) { this.getdata = function () { return $http({ ...

Utilize PHP to import an HTML file with JavaScript code into MySQL database

I've been attempting to use JavaScript to retrieve my location, but I'm facing an issue where when I click submit, the data is not getting entered into the page action.php. geolocation.php <form action="action.php" method="post"> < ...

Handlebars does not support loading data into variables using Express

My NodeJS/Express application utilizes Handlebars for templates, and everything works smoothly except when attempting to display data retrieved from an Express API. The data is successfully fetched and can be viewed in the Chrome debugger. In the problem ...