Is it safe to remove a property from the `0%` keyframe of a CSS animation if it is already declared in the class the animation is applied to?
The computed value of a property can vary depending on what CSS rules are applying to a given element, the specificity of these rules, whether the element has an inline style declaration for that property, whether a script is modifying the value of that property at runtime, etc.
If you want an animation to start from a predictable, and fixed, value, you will need to specify this value in the 0% keyframe so that it doesn't start animating from what the computed value happens to be at the time the animation starts instead.
You can leave out the 0% keyframe if you can guarantee that the computed value for that element at the time the animation is started is always a constant value. You must leave out the 0% keyframe if you want the animation to always start from whatever the computed value happens to be at the time, if it can change.
Similar rules apply to the 100% keyframe: if the animation needs to end with a fixed value regardless of what the computed value may be, you will need to specify the 100% keyframe; otherwise, if it needs to end with the same value as the computed value, you will need to leave it out.
Removing class does not stop keyframe animation in IE11
As pointed out by epascarello in the comments this is an IE11 bug, and the solution is to force the browser to redraw the affected element. In the example above simply updating the elements style.display
property was enough to stop the animation:
stopButton.addEventListener("click", function(){
banner.classList.remove("spin");
banner.style.display = "block";
})
In my real world problem I was using jQuery, so calling .show()
on my element after removing the class was enough.
CSS Animation property stays after animating
I think you're looking for animation-fill-mode
CSS3 property
https://developer.mozilla.org/en/CSS/animation-fill-mode
The animation-fill-mode CSS property specifies how a CSS animation should apply styles to its target before and after it is executing.
for your purpose just try to set
h2 {
animation: fadeIn 1s ease-in-out 3s;
animation-fill-mode: forwards;
}
Setting forwards value «the target will retain the computed values set by the last keyframe encountered during execution»
Do not reset keyframe animation when class removed
why do you remove the class? do not remove the class, just change the animationPlayState. a working example http://www.tutorialspark.com/css3/CSS3_Animation_Pause_Resume_Demo.php
if the class also does something else, then create two classes for it
React CSS Keyframes - animate when state removes component from DOM
You can use css keyframe and use onAnimationEnd event handler to trigger state change after the animation is finished. Also you can add style={{ animationFillMode: "forwards" }}
to the node to preserve the CSS properties of the last keyframe before removing it from the DOM.
Example:
{removeDom && (<button
style={{ animationFillMode: "forwards" }}
className="some animation class"
onAnimationEnd={()=>setRemoveDom(true)}
/>)}
Maintaining the final state at end of a CSS3 animation
Try adding animation-fill-mode: forwards;
. For example like this:
-webkit-animation: bubble 1.0s forwards; /* for less modern browsers */
animation: bubble 1.0s forwards;
Transition to default class upon removal of CSS class with animation
To get a transition effect, you can use the transition
-property.
The transition
-property can be used here, since every property you want to animate only has a start- and end-value.
Translating animation-percentages to seconds
To translate the percentages of your CSS Animation button-animation
to seconds, you just calculate 'percentage' * 'animation-duration'
.
This works for both the transition-duration
-property as well as for the transition-delay
-property.
Example:color
is being animated from 20% to 25%, which is a duration of 5% with a delay of 20%.
All in all, the animation should take 2 seconds.
So we calculate for:
transition-duration
:5% * 2s = 0.1s
transition-delay
:20% * 2s = 0.4s
With that, we can add transition: color 0.1s 0.4s
to the .default
-class.
Why add it to .default
, and not to .animation
?
If we were to add the transition
-property to .animation
, the following would happen:
- When adding
.animation
, there will be a transition-effect, since the element now has atransition
-property defined. - But when removing
.animation
, the element would no longer have atransition
-property defined, meaning there would be no transition.
Now, we want to transition on both adding and removing .animation
, meaning we want to have a transition
-property defined both when .animation
is present and when it is not. That means, transition
should not be defined in .animation
.
// JS only toggles '.animation'
document.querySelector("button").addEventListener("click", () => {
document.querySelector("div.default").classList.toggle("animation");
});
body {display: flex}
button {align-self: center}
div.default {
position: relative;
border: 2px solid black;
width: 100px;
height: 100px;
background: darkgreen;
}
/* Above code to make a visible working example */
div.default {
top: 20px;
color: white;
transition: top 0.4s, color 0.1s 0.4s;
}
div.default.animation {
top: 23px;
color: red;
}
<div class="default">Some text to see the "color"-property</div>
<button>Toggle ".animation"-class</button>
Add and Remove Keyframe on time
You can make use of the animation event. In your case the animation is defined as animation: rotation 20s infinite linear;
, so to stop the animation and start the next you need to look for the animationiteration
event.
I wrapped the elements in a <div>
for the event listener. At the same time this wrapper can be used for finding the next element to animate.
const container = document.getElementById('container');
//container.addEventListener('animationend', e => {
container.addEventListener('animationiteration', e => {
$(e.target).removeClass('cb2');
let next = e.target.parentElement.querySelector(`div#${e.target.id}~div.object`);
if(next){
$(next).addClass('cb2');
}else{
$(e.target.parentElement.querySelector(`div.object`)).addClass('cb2');
}
});
// initiate animation
$(container.querySelector(`div.object`)).addClass('cb2');
@keyframes rotation {
0% {
transform: rotateY(0deg)
}
10% {
transform: rotateY(55deg)
}
30% {
transform: rotateY(55deg)
}
60% {
transform: rotateY(230deg)
}
80% {
transform: rotateY(230deg)
}
100% {
transform: rotateY(360deg)
}
}
.object {
position: relative;
margin: auto;
height: 100px;
width: 100px;
-webkit-transition: -webkit-transform 2s linear;
-webkit-transform-style: preserve-3d;
-moz-transition: -moz-transform 2s linear;
-moz-transform-style: preserve-3d;
transition: transform 2s linear;
transform-style: preserve-3d;
transform: rotateY(230deg);
}
.cb2 {
animation: rotation 20s infinite linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div id="first" class="object">A</div>
<div id="second" class="object">B</div>
<div id="third" class="object">C</div>
</div>
Related Topics
How to Exclude a Specific Element from Inheriting CSS Rules
Css: Flex Box Not Printing All Pages on Firefox
Changing the Order of Grid Item Stacking in Material-Ui
How to Use CSS to Vertically Center the Text in an Anchor, Within a Li
Css3 Scale Transform on Parent Div But Keeping Constant Size in Some of the Associated Divs
How to Add Padding or Border to a Div and Keep Width and Height
CSS - Using One Background Image with Multiple Images on It
How to Set Selected and Hover Color of Listitem in Mui
Android Browser - Remove Outline Border When Anchor Is Focused
Change Background Color Every 30S (Fade Transition)
Easiest Way to Have a Bootstrap Layout Where the Burger Menu Is Always Visible
Using Grunt Grunt-Contrib-Less) for Compiling Bootstrap 3.1 Less in Visual Studio 2013
Bootstrap3 .Visible-* .Hidden-* Display Inline
Flexbox Space-Between and Align Right
CSS !Important Does Not Override Styles from External Stylesheets