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

Creating an HTML button that functions as a link to a specific section on the same page

I am interested in creating an HTML button that functions as a link to an item on the same page. Essentially, when this button is clicked, it should redirect to an item within the same page. Is there a way to achieve this using only HTML, CSS, and JavaScr ...

Circular CSS menu

What I'm Trying to Achieve: I am interested in developing a unique radial menu that includes interactive elements, such as the central image and the surrounding sections. It is imperative that the solution is compatible across all browsers. The examp ...

Issue with Bootstrap Navbar-Toggle Functionality in ASP.NET with Visual Studio 2010 Not Resolving

After installing a NuGet package, I proceeded to install Bootstrap which created the following folders: Contents containing Bootstrap CSS files Scripts containing .js files In the header of my Master Page, I included the scripts like this: <scrip ...

Text in a class button that is not skewed

I crafted a button for my website using a CSS class, aiming for a parallelogram shape by utilizing the skew function. The code worked like a charm, giving the button the desired shape. However, I encountered a dilemma where the text inside the button also ...

When hovering over individual links within a set of blocks, ensure that the other links are not affected or disrupted

I need help creating a forum category link guide. Similar to this example... Specifically, I want it to display as Forums > The Financial Roadmap Two issues I am facing are: when hovering over the link, it shifts down one row and how can I add blocks ...

PyScript <script type="py-editor"> Issue: SharedArrayBuffer cannot be used in an insecure environment

I am currently using PyScript to execute a basic Python script within my HTML file in order to show a pandas DataFrame. However, upon loading the page in the browser and attempting to run the code block by clicking the run button, I encounter an error rela ...

Implementing a queue with an on-click event

As a self-proclaimed Java nerd diving into the world of jQuery, I'm facing some challenges. My goal is to create 3 interactive boxes that behave in a specific way: when clicked, one box should come forward while the other two dim and stay in the back ...

Implement the Vue.js @click directive in a location outside of an HTML element

I've set up a link like this: <a href="#" @click="modal=true">Open modal</a> Here's the data setup: export default { data () { return { modal: false } } } Is there a way to trigger the cli ...

When the parent element has a fixed position, the child element will no longer maintain its floating property

I'm currently working on a fixed navigation panel that sticks in place while scrolling down. Here is the code I have so far: <header> <a class="logo" href="/">Logo_name</a> <nav> <a href="#">Menu_1</a& ...

Tips for retrieving user input and displaying it on an HTML page

I have encountered an issue with displaying user input in a table. The code for the table display is as follows: <tr ng-repeat="user in users" ng-class-even="'bg-light-grey'" ng-if="isLoading==false"> <td> ...

How to align a list item to the right using CSS

I'm having trouble aligning items in a list to the right and adjusting their width based on content length. Unfortunately, I haven't been able to make it work despite multiple attempts. Take a look at my code snippet below: .messages { over ...

How do I disable scrolling while the animation is running in CSS?

Is there a way to disable scrolling while animating in CSS without using overflow:hidden on the body tag? ...

Guide to interpreting an Angular expression using traditional JavaScript conventions

I have encountered an issue with the Angular app that I am currently working on. It needs to retrieve the Google Analytics ID from Angular in order to pass it to ga('create', 'UA-XXXXX-Y') using standard JavaScript in my index.html. &l ...

Tracking the progress of reading position using Jquery within an article

Here is an example of a reading progress indicator where the width increases as you scroll down the page: http://jsfiddle.net/SnJXQ/61/ We want the progress bar width to start increasing when the article content div reaches the end of the article c ...

Trouble with Showing Bootstrap 5 Icon

My current project involves creating a website using Bootstrap 5 icons, but I'm encountering an issue where the icon is not displaying correctly. The expected appearance should be like this [![Example1][1]][1], but it actually looks like this [![Examp ...

Tips for altering the color of an activated Bootstrap dropdown toggle

When the Dropdown menu is open, I would like to customize its default colors. Specifically, I want to change the border color and background using CSS. https://i.sstatic.net/vKwLE.png Below is the HTML code snippet: <div class="row menu"> <ul ...

The background positioning feature is experiencing some technical issues

Using Jekyll, I have code where the inline background-position changes based on the front-matter position I define: * { box-sizing: border-box; } body{ padding: 0; margin: 0; } .page__hero--overlay { position: relative; margin-bottom: 2em; ...

Is there a way to display multiple Bootstrap 5 modals simultaneously without automatically closing the previous ones?

My current project utilizes bootstrap 5.2, which is a departure from the previous version, bootstrap 3. In bootstrap 3, it was possible to open multiple modals on top of each other, creating an overlapping effect. However, in bootstrap 5 and 5.2, the behav ...

What is the best way to share an HTML element across multiple pages in Next.js?

I am in the process of developing a website that features a table of contents with links on the left side, content sections in the middle, and an overview on the right. For a visual representation of the general concept, please visit: Currently, all code ...

Manipulating CSS animations through JQuery

Currently, my animation is triggered by a :hover event. However, I would like to change it so that the animation starts when a button is clicked. Can someone guide me on how to manipulate the CSS using JQuery? //CSS .mouth{ top: 268px; left: 273px; ...