I'm using a CSS animation to slide a div in when the page loads. (Chrome)
I use animation-fill-mode: forwards;
to persist the new state.
From there I would like to have a simple hover animation that uses transform:scale(2);
and have it transition over 1 second.
My CSS:
.box{
background-color:blue;
width:100px;
height:100px;
margin: 0 auto;
animation-name: test;
animation-duration: 3s;
animation-fill-mode: forwards;
transition: 1s ease;
}
@keyframes test{
0% {
transform: translate(-200px)
}
100% {
transform: translate(0px);
}
}
.box:hover{
transform: scale(2);
}
View on Codepen
If I use a simple change on hover, like border-radius
it works:
.box{
transition: border-radius 0.25s ease;
}
.box:hover{
border-radius: 100%;
}
Somehow the initial CSS animation is interfering with a transform/transition for the hover state of the element.
If I change the hover to remove the animation-fill-mode
the transform
will work, but not the transition:
.box:hover{
animation-fill-mode:none;
border-radius: 100%;
}
Any ideas?
animation-fill-mode: both applies the rules of both backwards and forwards: The element will adopt the styles of the first keyframe before the animation begins, and the styles of the last keyframe after the animation ends.
By setting the animation-play-state to paused on hover, the animation will pause, your click targets will stop moving, and your users will be happy.
Triggering transitions You can trigger CSS transitions directly with pseudo classes like :hover (activates when the mouse goes over an element), :focus (activates when a user tabs onto an element, or when a user clicks into an input element), or :active (activates when user clicks on the element).
Why does transform not work when animation fill mode is forwards?
As per W3C pec: (emphasis is mine)
By default, an animation will not affect property values between the time it is applied (the ‘animation-name’ property is set on an element) and the time it begins execution (which is determined by the ‘animation-delay’ property). Also, by default an animation does not affect property values after the animation ends (determined by the ‘animation-duration’ property). The ‘animation-fill-mode’ property can override this behavior.
If the value for ‘animation-fill-mode’ is ‘forwards’, then after the animation ends (as determined by its ‘animation-iteration-count’), the animation will apply the property values for the time the animation ended.
The above means that the UA has to apply and maintain the transform
on the element even after the animation has ended. This would sort of imply that the transform
mentioned within the animation gets precedence and hence the transform
that is mentioned within the :hover
state has no effect.
When animation-fill-mode: none
or animation-fill-mode: backwards
is applied then the UA does not have to maintain the transformed state after the animation has ended (meaning it kind of becomes like transform: none
) and so the transform
within the :hover
selector works.
This behavior is consistent in latest versions of Chrome and Firefox. In IE11 and Edge the transform
that is specified within the :hover
selector has no effect irrespective of what value is provided for the animation-fill-mode
property.
Why does transition not work when even when fill mode is changed to none?
I am not sure if the code in CodePen is the original one or if you made any changes for testing but the transition
property is wrongly specified in that demo and that is the reason why transition does not happen.
The code that is present is:
transition: scale 1s ease;
but scale
is not the property that needs to be transitioned. It is only the type of transform that needs to be done. The property is transform
and hence the code should be as below:
transition: transform 1s ease;
If you do this change then the transition
will work if the animation-fill-mode
is changed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With