The CSS transition is failing to revert to its original state after being combined with animations

My goal is to create a loading animation using CSS transitions and animations. I have managed to achieve the initial loading effect by scaling with transition and then animating it to scale out on the x-axis. However, when attempting to transition back to the original state, it snaps back instead of smoothly transitioning. While I could use animation for the entire process, I want to ensure that the page continues to load without requiring additional JavaScript logic to handle it. Ideally, the transition should occur automatically without any sudden movements.

Upon clicking the snippet below, the first click works as intended. However, subsequent clicks cause it to snap back to the original state without transitioning. Changing the property to something like opacity in the animation section works correctly, leading me to believe there may be an issue with the browser not recognizing the current scaled value. Is this a bug or am I missing something in my implementation?

document.querySelector('.wrapper').addEventListener('click', () => {
    document.querySelector('.wrapper').classList.toggle('loading')
})
.wrapper{
  position:fixed;
  top: 0;
  left: 0;
  width:  100%;
  height: 100%;
}

.wrapper > div{
  color: white;
  display:flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: blue;
  transition: transform 500ms ease-out;
  transform: scale(1);
}

.wrapper.loading > div{
  transform: scale(0.2, 0.002);
  animation: loading 1000ms ease-out infinite;
  animation-delay: 500ms;
}

@keyframes loading {
  0%{
    transform: scale(0.2, 0.002)
  }
  50%{
    transform: scale(0.5, 0.002)
  }
  100%{
    transform: scale(0.2, 0.002)
  }
}
<div class="wrapper">
  <div>click me</div>
</div>

Answer №1

Summary:

In my theory, the reason behind this phenomenon is that CSS transition gives a class two distinct states and switches between them. When you remove the class without changing its state, it simply disappears. To solve this issue, I suggest adding an additional class to revert it back.


CSS transitions operate by setting up two states for an element through CSS styling. Essentially, you outline how the element appears with the "loading" class and how it appears without the "saved" class (its default appearance). Removing the "loading" class triggers a transition to the other state based on the predefined settings in place for the element without the "loading" class.

If the CSS transition properties apply to the element sans the "loading" class, they will affect both transitions accordingly.

Your current transition CSS rules only target the ".saved" class, hence when it is removed, there are no directives for the transition. To counteract this, consider introducing a new class like ".fade" that remains on the element at all times, allowing you to define your CSS transition settings within that class to ensure they are consistently implemented.

Answer №2

I am not aware of a pure CSS solution to fix this issue.

One workaround is to include a different class with an animation that reverts back to its original state using JavaScript.

const wrapper = document.querySelector(".wrapper");

wrapper.onclick = () => {
  if ([...wrapper.classList].includes("loading")) {
    wrapper.classList.add("restore");
  } else {
    wrapper.classList.remove("restore");
  }
  
  wrapper.classList.toggle("loading");
};
.wrapper {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.wrapper>div {
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: blue;
  animation: none;
  transform: scale(1);
  transition: transform 500ms ease-out;
}

.wrapper.restore>div {
  animation: restore 500ms ease-out;
}

.wrapper.loading>div {
  transform: scale(0.2, 0.002);
  animation: loading 1000ms 500ms ease-out infinite;
}

@keyframes restore {
  0% {
    transform: scale(0.2, 0.002);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes loading {
  0% {
    transform: scale(0.2, 0.002)
  }
  50% {
    transform: scale(0.5, 0.002)
  }
  100% {
    transform: scale(0.2, 0.002)
  }
}
<div class="wrapper">
  <div>click me</div>
</div>

Answer №3

To control the number of times an animation repeats, you can utilize the animation iteration count property:

.element {
   animation-iteration-count: 3;
}

Alternatively, if you want to freeze the animation at the end, you can apply the fill mode property:

-webkit-animation-fill-mode: forwards;

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

A unique flex layout with scrolling capabilities specifically designed for optimal performance in Chrome

This layout includes a header, footer, sidebar, and a scrolling main content section. You can view a demonstration of this design on Bootply. <div class="parent"> <div>HEADER</div> <div class="main"> <div class="side"> ...

In PHP, the hidden input type doesn't always provide true concealment within a form if the value being passed

I am attempting to populate a hidden input field with the value of an XML string generated from an array. However, when I set the hidden field value using the XML string, it is being displayed in the HTML output. Surprisingly, if I use plain text as the va ...

Navigate only within the tbody section of the Material UI Table by scrolling

Utilizing the material-ui Table component to build a table with a sticky header presents a challenge. The default behavior is for the scroll to encompass both the thead and tbody of the table. However, I specifically require the scroll functionality to be ...

What is the best way to include a background image in a div within a React component?

I'm currently following a tutorial on creating an RPG game using React. The tutorial can be found at this link. I am trying to replicate the presenter's code by typing it out myself. However, I'm running into an issue when attempting to add ...

The current layout of the div is hindering the ability to switch from vertical scrolling to horizontal scrolling

I'm currently utilizing this scroll converter tool to transform vertical scrolling into horizontal scrolling. However, despite correct script inclusion and initialization, the conversion is not working as expected. It seems like there might be an issu ...

Challenges in using HAML5 Canvas for mathematical applications

Hey there! I'm currently working on utilizing the canvas element to form various shapes, but I've encountered a few challenges when it comes to the mathematical aspect. Issue 1: I need to calculate an angle that is relative to the preceding line ...

How can I arrange the ng-class based on the clicked item's order?

http://plnkr.co/edit/pUtuZy?p=preview In this scenario, there are three different border classes available: .border1 { border: 1px solid #66FFFF; } .border2 { border: 1px solid #33CCFF; } .border3 { border: 1px solid #0099FF; } The goal is to as ...

What could be causing this image to disregard the designated width value?

https://i.stack.imgur.com/bPH4t.png While working on my project with Next.js, I encountered an issue with the IconText component provided by Next.js. Even though I specified a width value for the image, it seems to be ignoring it. Below is the structure o ...

AngularJS has the ability to handle the value of one input based on the value of another input

How can I ensure that if one input has a value, the other must also be filled in AngularJS? I'm looking for the best approach to handle this requirement in an angular way. Any suggestions? Below is my code: <div class="form-group recipe_item" ng ...

Issue with background/hero video not adjusting its size

I've been experimenting with creating a page that features a video as the background, but no matter what I try, the video never seems to resize properly. The image below shows how it looks: image in question body { margin: 0; } .hero-se ...

Angular JS has a unique feature of a scrollable drop-up menu that allows

Here is the code snippet for my Dropup component: <div class="dropup"> <button class="btn btn-primary btn-raised dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false> ...

storing information in HTML using Django

Recently, I have been learning about Django Rest and I am now trying to display some JSON data in HTML. The JSON data I have is: {'Resul': {'Period Start': '2017-01-01', 'Period End': '2017-12-12'}} When ...

When attempting to select an option from the dropdown menu, I encounter an issue where the

My code is not behaving as expected. Whenever I click on the child elements, the dropdown changes to display: none. I am encountering an error when clicking on the input frame and displaying:none. How can I resolve this issue? I would like to be able to ...

At times, the animation in SetInterval may experience interruptions

I have created an animation using a sequence of images. The animation runs smoothly with the setinterval function, but for some reason, it occasionally pauses. I've shared a fiddle where you can see this pause happening. Click Here to See the Unwante ...

Display or conceal a field based on the content of another field using jQuery

Is there a way to hide or show a field on my website based on the value in the shopping cart? I've created a function for this, but I'm struggling with the condition. Can you help me figure out how to write it correctly? <script> $(docume ...

Step-by-step guide on generating a fluid list with Express and HTML

Looking to create a dynamic list by fetching data from a JSON file. I want the list items to redirect me to specific content based on their IDs when clicked. However, my current approach is not working as expected, and the list needs to be truly dynamic. ...

What is the best way to create a never-ending horizontal animation that moves a logo image from right

I have a dilemma with displaying my logo images. I have more than 10 logos, but I want to showcase only 6 of them on page load. The rest of the logos should slide horizontally from right to left in an infinite loop. Can anyone assist me with creating keyf ...

How can the color of the <md-toolbar> be customized?

Here is a glimpse of how my code appears on CodePen: I am aiming to have the background color of "Sidenav Left" match that of "Menu Items", which is designated by the class .nav-theme { background-color: #34495E } I attempted to override it like this ...

Rearranging the @use directive in Sass

Here are some style snippets: tokens.scss .text-center { text-align:center; } .bold { font-weight: bold; } @mixin text-style-1 { font-size: 1.2rem; font-weight: bold; } component/card.scss @use "../token.scss" as tokens; .card { @i ...

Error message: Failure to retrieve / on the Express application

Embarking on a new project using express, I've set up the foundation with an index.js file in my project folder: var express = require('express'); //App setup var app = express(); var server = app.listen(4000, function(){ console.log(&a ...