32

While working with CSS keyframe animations I found that when I give an element two animations like:

.element {
    animation: animate1 1000ms linear infinite,
               animate2 3000ms linear infinite;
}

If both of the animations animate using the transform property only the last one triggers through cascading. But if the @keyframes animations are lets say one margin or display or some other css attribute and the other uses transform then they both trigger.

here is a codepen example with the relevant code below.

CSS

@keyframes move {
    0%, 100% { transform: translateX(0px); }
    50% { transform: translateX(50px); }
}
@keyframes skew {
    0%, 100% { transform: skewX(0deg); }
    50% { transform: skewX(15deg); }
}
@keyframes opacity {
    0%, 100% { opacity: 1; }
    50% { opacity: .25; }
}

.taco {
    animation: skew 2000ms linear infinite,
               opacity 4000ms linear infinite;
}

In the Above they both trigger

.burger {
    animation: skew 2000ms linear infinite,
               move 4000ms linear infinite;
}

In the above only the last triggers (through cascading)- why?

Anyone have a solution for this without using js? Or is this something that just doesn't work? The example is quite simple and I know that I could combine the animations into one and not have to declare both but this was a test for a more complex animation I was working on.

thanks

3 Answers 3

46

You cannot animate same attribute ( here transform attribute ) more than once, on a same element, the last one will overwrite other,

You should put your target element into a div, and apply one transform-animation on the div and other transform-animation on the target element....

.div_class
{
    animation:animate1 1000ms linear infinite;
}

.element
{     
   animation:animate2 3000ms linear infinite;
}
Sign up to request clarification or add additional context in comments.

4 Comments

thanks for the idea of wrapping in a div, the two transform animations needed different timings.
"You cannot animate same attribute more than once on a same element" This doesn't seem entirely accurate though, see: jsfiddle.net/j83m5ha5/4. Here the same element chains the same attribute on the same class. Why does this work, but not with transform?
@StephanMuller , I have checked your animation, and the second animation (out) is overwriting the first one( in), Just increase the duration of first animation , lets say make it 10 sec, and see the effect , you will find that it is a 1 min animation, because 2nd animation is overwriting the 1st one..
it would be nice if you could optionally use transform values as stand-alone properties. translateX: 4em; skewX: 45deg; It would make animating a lot easier.
11

For the same reason that

transform: skewX(45deg);
transform: translateX(4em);

won't skew the element but will only move it. And if you want to both skew and move it then you need to chain them transform: skewX(45deg) translateX(4em)

You'll have to do something like

@keyframes t {
    25% { transform: skewX(15deg); }
    50% { transform: skewX(0deg) translateX(50px); }
    75% { transform: skewX(15deg); }
}

You don't need to explicitly specify 0% and 100% keyframes - they'll be automatically generated - see the CSS Animations spec.

And then you can use

animation: t 4000ms linear infinite,
        opacity 4000ms linear infinite;

One more thing you should be careful about: skewX(angleValue) translateX(lengthValue) happens to be the same as translateX(lengthValue) skewX(angleValue). However, most of the times, the order in which you apply transforms matters. You'll get different results for skewX(angleValue) translateY(lengthValue) and translateY(lengthValue) skewX(angleValue).

Comments

1

@StephanMuller's jsfiddle is pretty much the answer, that syntax has worked for me http://jsfiddle.net/j83m5ha5/4

div {
background:green;
width:100px;
height:100px;
-webkit-animation: in 2s 200ms  forwards, out 1s 2200ms forwards;
}

I believe the OP has asked the question at hand because he wanted to standardise his animations and just apply them as needed, take this recent practice code from my classes: https://jsfiddle.net/kgLc56w4/

#b15{
top:200px;
left:200px;
background:#ff3399;
-webkit-animation: r4 ease-in-out 2s forwards 24s, s4 ease-in-out 2s forwards 30s;
}

Each block moves only in one direction, so instead of doing the grunt work of making 15 animations, I just used simpler 8. I know that this could've been done a lot simpler, but that wasn't the point of the practice.

What I changed though, I used Stephan's syntax on the last 15th element to move it once more and it works.

You just need to be careful of the timings, in Stephen's case, if you increase the duration of the 1st (in) animation, you need to increase the delay of the 2nd (out).

Example:

-webkit-animation: in 20s 200ms  forwards, out 1s 20200ms forwards;

Hopefully this helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.