CSS Transform and Transition on Hover Do Not Work After Animation-Fill-Mode: Forwards

CSS transform and transition on hover do not work after animation-fill-mode: forwards

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.

Transition doesn't work after animation forwards

Still don't know what's wrong with keyframes in chrome/safari, but have found simple workaround.

Now first 'before'-element is on right with no width right: 0; width: 0;.
On hover it moves to left with 100% width, that begins to transitionally grow: left: 0; right: auto; width: 100%;.

Finally, when hover was lost, 'before' starts to decreasing, resting on the right end again.

New code:

button {
padding: 5px 0;
position: relative;
border: none;
border-radius: 0;
background: transparent;
outline: none;
cursor: pointer;
font-weight: 700;
text-transform: uppercase;

&:before {
content: '';
position: absolute;
bottom: 0;
right: 0;
width: 0;
height: 4px;
border-radius: 2px;
background: blue;
transition: all .25s;
}

&:hover {

&:before {
left: 0;
right: auto;
width: 100%;
}
}
}

Codepen

How to animate element again, after animation-fill-mode: forward?

Use two animations like below:

.main-image {
transition: transform .5s ease-in-out;
height: 50px;
margin: 10px;
background: red;
}

#portfolio:hover #portfolio-image {
transform: scale(1.1);
}

@keyframes fade {
100% {
opacity: 1;
}
}
@keyframes move {
0% {
transform: translateY(-30%);
}
}

#portfolio .main-image {
opacity: 0;
animation:
0.5s ease-out 0.2s fade forwards, /* forwards only for opacity */
0.5s ease-out 0.2s move;
}
<div id='portfolio' class='main-block'>
<div id='portfolio-image' class='main-image'></div>
</div>

CSS animation with fill-mode including transition not working in firefox properly

Well, I added a keyframe for the start point 0% to get it to work:

@keyframes test{
0% {
transform: translate(-200px);
}
100% {
transform: translate(0px);
}
}

Using the above, you could remove the transform property form the .box element.

Also, for the old versions of web browsers, consider using vendor prefixes such as -webkit- and -moz-, ... for the @keyframes and the other CSS3 properties.

PS: I tested the demo with FF 9.0.1. This issue may appear only in earlier versions of web browsers. In fact, web browsers try to fix your bad-coding but only the smarters will win!

WORKING DEMO

Update

In order to fix the rendering issue (when the animation starts) you need to change the transition-property from all to the specific properties you really want. (border-radius in this case):

.box{
animation-name: test;
animation-duration: 3s;
animation-fill-mode: forwards;
transition: border-radius 0.25s ease;
}

The problem was because of the conflict between animation and transition for the transform property.

UPDATED DEMO

Execute :hover and :hover:after animation with keyframes on component load

I've fixed the animation with an additional element providing the :after feature:

.module .heading {
font-size: 2.75rem;
font-weight: 700;
margin-bottom: 2rem;
font-family: 'Oswald', sans-serif;
font-weight: 200;
color: var(--text-color-dark);
}

.module .active {
display: inline-block;
position: relative;
color: var(--text-color-dark);
animation-iteration-count: 1;
animation-fill-mode: forwards;

.reveal-line {
transform: scaleX(1);
transform-origin: bottom left;
content: '';
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: var(--primary-color);
transform-origin: bottom right;
transition: transform 0.6s ease-out;
animation: loadInAnimation ease 1.5s;
}
}

@keyframes loadInAnimation {
0% {
width: 0%;
}

100% {
width: 100%;
}
}
<h3 className='heading reveal'>Unsere Angebote<div className='reveal-line' /></h3>

Hover animation makes initial animation rerun after mouse out

If you do not want the initial state animation to run again after you mouse out of the hover state and you want the element to return to its previous orientation. You will need to add a class to the foo element using JavaScript and add in CSS for that class that no longer allows that animation to run.

const fooEl = document.querySelector(".foo");

fooEl.addEventListener("mouseleave", () => {
fooEl.classList.add("stopped");
})
.foo {
margin: auto;
margin-top: 100px;
padding: 1em;
width: fit-content;
border: solid 1px black;
background: red;
color: white;
font-size: 2em;

/* The initial animation */
animation: kf-initial 2s;
}

.stopped {
animation: none;
}

.foo:hover {
/* The infinite animation */
animation: kf-hover 10s infinite;
}

@keyframes kf-initial {
from {transform: scale(0.2)}
to {transform: scale(1)}
}

@keyframes kf-hover {
100% {transform: rotate(1turn)}
}
<div class="foo">
Hello world
</div>


Related Topics



Leave a reply



Submit