Running a CSS keyframes animation can be achieved by removing the class associated with it

Is there a way to reverse the CSS animation when a class is removed? I'm trying to achieve this on my simple example here: https://codepen.io/MichaelRydl/pen/MWPvxex - How can I make the animation play in reverse when clicking the button that removes the class?

const elementTwo = document.getElementById("element-two");
const addButton = document.getElementById("add-button");
const removeButton = document.getElementById("remove-button");

addButton.addEventListener("click", () => {
  elementTwo.classList.add("animated");
})

removeButton.addEventListener("click", () => {
  elementTwo.classList.remove("animated");
})
button {
  margin-top: 10px;
}

#element-one {
  width: 500px;
  height: 30px;
  background-color: lightgrey;
  border-radius: 8px;
  positon: absolute;
}

.animated {
  width: 100%;
  height: 100%;
  background-color: lightblue;
  border-radius: 8px;
  position: relative;
  top: 0;
  left: 0;
  animation-name: animateWidth;
  animation-duration: 0.4s;
}

@keyframes animateWidth {
  0% {
    width: 0%;
  }
  100% {
    width: 100%;
  }
}
<div>
  <div id="element-one">
    <div id="element-two"></div>
  </div>
  <button id="add-button">Add Class</button>
  <button id="remove-button">Remove Class</button>
</div>

Specifically, I want the animation to play backwards when the second button removes the class that was added by the first button. Can anyone help me with this?

Thank you for your assistance.

Answer №1

It appears that your primary concern is implementing a transition:

const elementTwo = document.getElementById("element-two");
const addButton = document.getElementById("add-button");
const removeButton = document.getElementById("remove-button");

addButton.addEventListener("click", () => {
  elementTwo.classList.add("animated");
})

removeButton.addEventListener("click", () => {
  elementTwo.classList.remove("animated");
})
button {
  margin-top: 10px;
}

#element-one {
  width: 500px;
  height: 30px;
  background-color: lightgrey;
  border-radius: 8px;
  positon: absolute;
}

[id=element-two] {
  width: 0;
  height: 100%;
  background-color: lightblue;
  border-radius: 8px;
  position: relative;
  top: 0;
  left: 0;
  transition: width 0.4s;
}

.animated {
  width: 100%;
}
<div>
  <div id="element-one">
    <div id="element-two"></div>
  </div>
  <button id="add-button">Add Class</button>
  <button id="remove-button">Remove Class</button>
</div>

Additionally, you might want to explore using transform: scaleX() for smoother animations, as it can enhance performance by reducing the browser's processing load compared to using width:

const elementTwo = document.getElementById("element-two");
const addButton = document.getElementById("add-button");
const removeButton = document.getElementById("remove-button");

addButton.addEventListener("click", () => {
  elementTwo.classList.add("animated");
})

removeButton.addEventListener("click", () => {
  elementTwo.classList.remove("animated");
})
button {
  margin-top: 10px;
}

#element-one {
  width: 500px;
  height: 30px;
  background-color: lightgrey;
  border-radius: 8px;
  overflow: hidden;
  positon: absolute;
}

[id=element-two] {
  width: 100%;
  height: 100%;
  background-color: lightblue;
  border-radius: 8px;
  position: relative;
  top: 0;
  left: 0;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s;
}

.animated {
  transform: scaleX(1);
}
<div>
  <div id="element-one">
    <div id="element-two"></div>
  </div>
  <button id="add-button">Add Class</button>
  <button id="remove-button">Remove Class</button>
</div>

Answer №2

To ensure the transition/animation applies correctly, make sure to assign it to the element where you want the effect to occur. This will ensure the effect triggers both when added and removed. Here's an example:

const elementOne = document.querySelector(".element-one");
const addButton = document.getElementById("add-button");
const removeButton = document.getElementById("remove-button");

addButton.addEventListener("click", () => {
  elementOne.classList.add("animated");
})

removeButton.addEventListener("click", () => {
  elementOne.classList.remove("animated");
})
button {
  margin-top: 10px;
}

.element-one {
  width: 500px;
  height: 30px;
  background-color: lightgrey;
  border-radius: 8px;
  positon: absolute;
  transition: background-color 1000ms linear;
}

.animated {
  background-color: lightblue;
}
<div>
  <div class="element-one">

  </div>
  <button id="add-button">Add Class</button>
  <button id="remove-button">Remove Class</button>
</div>

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

What is the best way to structure this React state container for modularity?

At my workplace, we have developed a state container hook for our React application and related packages. Before discussing what I'd like to achieve with this hook, let me provide some background information. Here is the functional code that's co ...

The JQuery script is not producing any results

After integrating a script into my website template, it is not functioning as expected. I suspect there may be a conflict with JavaScript, but upon inspecting with firebug, I am unable to identify any abnormalities. Here is the link for reference: Link ...

Why should you use DIV comment tags in HTML code and how can you automate their implementation?

As I've been browsing through the codes of various professional websites, I couldn't help but notice how the HTML code is often neatly commented like this: <!-- END DIV Main Menu --> This type of commenting can be really beneficial, don&a ...

Accessing the next and previous elements using jQuery

Aug: <input type="text" value="100000" name="targetMonth_8" id="targetMonth_8" class="targetMonth" disabled> Sep: <input type="text" value="100000" name="targetMonth_9" id="targetMonth_9" class="targetMonth" disabled> Oct: <input type="text" ...

How to style the background color of the selected option in a <select> element using

Is there a specific style I can use to change the color of a selected option in a dropdown menu? For example: <HTML> <BODY> <FORM NAME="form1"> <SELECT NAME="mySelect" SIZE="7" style="background-color:red;"> <OPTION>Test 1 &l ...

Guide on attaching an onclick function to a search bar

I found a search bar code on this website and I want to enhance it by adding a function that redirects users to a URL when they click on the search icon. Here is the existing code: <svg xmlns="http://www.w3.org/2000/svg" style="display:none"> ...

Unable to link to 'mdMenuTriggerFor' as it is not a recognized attribute of 'button'

During the execution of my angular application using ng serve, I encounter the following error: Can't bind to 'mdMenuTriggerFor' since it isn't a known property of 'button' Despite importing all the necessary components, I a ...

"Apple TV now features an iOS app that allows users to watch YouTube videos

I am interested in developing an iOS application that can play YouTube videos in a UIWebView window. Users should have the option to play the videos directly on their iOS device or stream them via AirPlay to an AppleTV. The content displayed in the UIWebV ...

Programmatically searching individual columns in Datatables is a powerful feature that

I am currently working on creating a jQuery datatable with search functionality in each column, using the example provided on the datatables page found at https://datatables.net/examples/api/multi_filter.html Specifically, I want to be able to search the ...

Discover the complete file path using node.js incorporating the express-busboy module

I am currently utilizing node.js and express-busboy for the purpose of uploading a file via a file input form to my server. Once uploaded, the file will be stored in a directory with a path resembling something like root/useruploaded/formattached/somerando ...

Is it Appropriate for Custom React Hooks to Trigger Re-Render of Related Components?

I have just developed a custom hook that internally uses useState and useEffect. After importing this hook into another React function component called ComponentA, I noticed that ComponentA re-renders every time the state within the custom hook changes. ...

Error: Unrecognized error encountered while using Angularjs/Ionic: Property 'then' cannot be read as it is undefined

codes: js: angular.module('starter.services', ['ngResource']) .factory('GetMainMenu',['$http','$q','$cacheFactory',function($http,$q,$cacheFactory) { var methodStr = 'JSONP' ...

Looking for a regular expression to require either a dollar sign ($) or a percentage symbol (%) but not

At the moment, I currently have this input field set up on an HTML page within my Angular 9 application: <input type="text" formControlName="amountToWithholdInput" onkeyup="this.value = this.value.replace(/[^0-9.%$]/, &ap ...

Transmitting information from directive to parent scope controller

I've successfully implemented a directive that generates a Google map on the page. Now, my goal is to pass the map object back out of the directive and into the parent controller. This will allow me to utilize it in various methods as needed. While ...

Adaptive text sizing within Microsoft Outlook

I am facing a challenge in making the font size of my email signature responsive. Although VW seems to be the solution, it doesn't seem to work in Outlook. I have attempted using CSS, but it appears that inline CSS might be necessary. However, I am un ...

Is it acceptable to compare a boolean with a string?

In my code, I have a variable called isRefreshed which is initially declared like this: var isRefreshed = ''; Sometimes, in certain scenarios, isRefreshed can be assigned a boolean value, for example: isRefreshed = false; Now, there is an if ...

I'm having trouble displaying the content of my list items within the div

In my code, I have a class called "ignicoes" that includes a list as one of its attributes. This list contains other attributes such as dispositivo, latitude, longitude, and more. My goal is to retrieve the contents of this list and display them within my ...

Searching dynamically using class names with JQuery

I am seeking to create a dynamic search input based on the class names within the span tags. However, I am struggling with displaying the class name that I have identified. My goal is to show the class names that match the entered value in the input on the ...

Tips for efficiently waiting for the outcome in a unified function for multiple callbacks within node.js

Perhaps the question title is not the most appropriate, but let me explain what I am trying to achieve in my code // First Callback Function connection_db.query(get_measure_query,function(err,user_data1){ if(err){ // throw err; ...

``Please note that the Sinon spy.called method is currently not

Context In my setup, a small server receives data from a machine. Each time a message is received, a function in a dispatcher object is called, which simply logs everything it receives to the console. Issue While I can see the logs in the console, Sinon ...