Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should :hover pseudo state style change work after CSS animation completes

Should style changes specified on a pseudo state such as :hover work after a CSS animation has completed running on the element?

EDIT: Perhaps more pertinently, I should ask: why does applying 'forwards' on an animation prevent a more specific style change from overriding?

EDIT 2: Turns out that this is actually a cross browser issue. E.g. Chrome (I was running Version 38.0.2125.111) behaves incorrectly but Firefox handles it as per the specs.

Long story short: According to the specs (as quoted by chrona below) adding !important to the override should render the style. However, at present, only Firefox handles this correctly.

Here is a reduction:

@keyframes go {
  0% {
    background: green;
  }
  100% {
    background: pink;
  }
}

@-webkit-keyframes go {
  0% {
    background: green;
  }
  100% {
    background: pink;
  }
}

.box {
  animation: go 3s forwards;
  -webkit-animation: go 3s forwards;
  
}

.box:hover {
    background: orange!important;
  cursor: pointer;
 }
<div class="box">Hover states don't work after animation</div>

I am unable to find information relating to this, nothing in the spec either: http://www.w3.org/TR/css3-animations/

Anybody know if a) this should be possible? b) how to make hover states work on an element once the animation ends?

like image 768
Ben Frain Avatar asked Nov 06 '14 11:11

Ben Frain


People also ask

Can you animate pseudo-elements?

As you have seen, the ::before and ::after pseudo-elements can be used in several different ways to produce interesting animated effects that give life to our designs.

Is hover an animation?

A CSS hover animation occurs when a user hovers over an element, and the element responds with motion or another transition effect. It's used to highlight key items on a web page and it's an effective way to enhance your site's interactivity.

How do you transition after CSS?

after is not a valid value of transition . Instead put transition as a property of the :after selector. You can also have a different transition on the hover in and hover out state. This allows us to have a delay to show the pseudo-element but no delay to hide it.

Why is animation not working in CSS?

Even if you've assigned a keyframes rule to an element, it still may not appear to play if you haven't set an animation-duration. By default, a CSS animation cycle is zero seconds long. To override this, add an animation-duration rule to your targeted element with a seconds value, in the same block as animation-name.


3 Answers

  • a)

About why does it happen, I can't state for sure. But it obviously is related to the animation-fill-mode property that you're setting to be forwards. That, by definition, sets the visual style of the element to be the last keyframe of the animation:

forwards
After the animation ends (as determined by its animation-iteration-count), the animation will apply the property values for the time the animation ended.

MDN's definition is a bit more clear:

forwards
The target will retain the computed values set by the last keyframe encountered during execution. The last keyframe encountered depends on the value of animation-direction and animation-iteration-count:

But I don't know why does it not allow the :hover state to override the styles.

  • b)

Now, about how to make it work, you could remove the forwards property from the animation. In this case, you'd need to reverse the animation, so the original state of the element (when the animation ends, and removes the visual effect), is the color that you want it to be fixed:

@keyframes go {
  0% {
    background: pink;
  }
  100% {
    background: green;
  }
}

@-webkit-keyframes go {
  0% {
    background: pink;
  }
  100% {
    background: green;
  }
}

.box {
  animation: go 2s;
  -webkit-animation: go 2s;
  -webkit-animation-direction: reverse;
  animation-direction: reverse;
  background: pink;
}

.box:hover {
    background: orange;
  cursor: pointer;
 }
<div class="box">Hover states don't work after animation</div>
like image 60
LcSalazar Avatar answered Oct 12 '22 23:10

LcSalazar


Quoted from the CSS Animations Working Draft

CSS Animations affect computed property values. During the execution of an animation, the computed value for a property is controlled by the animation. This overrides the value specified in the normal styling system. Animations override all normal rules, but are overriden by !important rules.

and a bit further down (Animation Duration):

[…] and an animation that fills forwards will retain the value specified at the 100% keyframe, even if the animation was instantaneous. Also, animation events are still fired.

As you are animating the background it cannot be overriden by default (except for !important rules). If you don't want to use !important you should go by LcSalazar's answer. (Currently only Firefox reacts as described in the specs [6th Nov 2014])

@keyframes go {
  0% {
    background: green;
  }
  100% {
    background: pink;
  }
}

@-webkit-keyframes go {
  0% {
    background: green;
  }
  100% {
    background: pink;
  }
}

.box {
  animation: go 3s forwards;
  -webkit-animation: go 3s forwards;
  
}

.box:hover {
    background: orange !important;
  cursor: pointer;
 }
<div class="box">Hover states don't work after animation</div>
like image 34
chrona Avatar answered Oct 13 '22 00:10

chrona


Actually I don't really understand your question, may be you need the effects like this? http://jsfiddle.net/abruzzi/5td8w6jx/

@keyframes go {
    0% {
        background: green;
    }
    100% {
        background: pink;
    }
}
@-webkit-keyframes go {
    0% {
        background: green;
    }
    100% {
        background: pink;
    }
}


.box {
    animation: go 3s forwards;
    -webkit-animation: go 3s forwards;
}
.box:hover {
    -webkit-animation: none;
    background: orange;
    cursor: pointer;
}

However, with these codes, when you mouseout the text, the animation will be replay.

like image 28
Abruzzi Avatar answered Oct 12 '22 22:10

Abruzzi