Extending the final state of the first animation for the translated item

I know what is asked several times here, but I ask for a different approach to these animations.

Problem:

The second box has several animations, trying to create the same effect as the first. The transform property seems to be overwritten (as it should) *. I am trying to extend the 1st animation (2nd drawer) with the properties of the 2nd animation. Tried to use animation-fill-mode: forwards , but without success. Maybe I'm missing something basic. Is this possible with vanilla CSS?

* Link

The "animation name" property determines the list of animations used. If multiple animations are trying to change the same property, then the animation closest to the end of the list of names ends.


Demand:

Separate move2-right and move2-down keyframe rules, but work on the same element while maintaining the 1st animation transformation. If there is an alternative approach to this kind of animation, please help me through it.


Current Output:

 .animation-1, .animation-2 { width: 200px; height: 200px; display: inline-block; background: white; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } .movable-1, .movable-2 { background: #41A186; width: 50px; height: 50px; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); text-align: center; vertical-align: middle; line-height: 50px; } .movable-1 { -webkit-animation-name: move1; animation-name: move1; -webkit-animation-duration: 4s; animation-duration: 4s; -webkit-animation-delay: 0s; animation-delay: 0s; -webkit-animation-fill-mode: forwards; animation-fill-mode: forwards; } .movable-2 { -webkit-animation-name: move2-right, move2-down; animation-name: move2-right, move2-down; -webkit-animation-duration: 2s, 2s; animation-duration: 2s, 2s; -webkit-animation-delay: 4s, 6s; animation-delay: 4s, 6s; -webkit-animation-fill-mode: forwards, forwards; animation-fill-mode: forwards, forwards; } @-webkit-keyframes move1 { 0% { -webkit-transform: translateX(0px); transform: translateX(0px); } 50% { -webkit-transform: translateX(30px); transform: translateX(30px); } 100% { -webkit-transform: translateX(30px) translateY(50px); transform: translateX(30px) translateY(50px); } } @keyframes move1 { 0% { -webkit-transform: translateX(0px); transform: translateX(0px); } 50% { -webkit-transform: translateX(30px); transform: translateX(30px); } 100% { -webkit-transform: translateX(30px) translateY(50px); transform: translateX(30px) translateY(50px); } } @-webkit-keyframes move2-right { 0% { -webkit-transform: translateX(0px); transform: translateX(0px); } 50% { -webkit-transform: translateX(30px); transform: translateX(30px); } 100% { -webkit-transform: translateX(30px); transform: translateX(30px); } } @keyframes move2-right { 0% { -webkit-transform: translateX(0px); transform: translateX(0px); } 50% { -webkit-transform: translateX(30px); transform: translateX(30px); } 100% { -webkit-transform: translateX(30px); transform: translateX(30px); } } @-webkit-keyframes move2-down { 0% { -webkit-transform: translateY(0px); transform: translateY(0px); } 50% { -webkit-transform: translateY(50px); transform: translateY(50px); } 100% { -webkit-transform: translateY(50px); transform: translateY(50px); } } @keyframes move2-down { 0% { -webkit-transform: translateY(0px); transform: translateY(0px); } 50% { -webkit-transform: translateY(50px); transform: translateY(50px); } 100% { -webkit-transform: translateY(50px); transform: translateY(50px); } } 
 <div class="animation-1"> <div class="movable-1">1</div> </div> <div class="animation-2"> <div class="movable-2">2</div> </div> 

Here is a fiddle you can play: JSfiddle

+7
css css3 css-transforms css-animations
source share
1 answer

As far as I know, this is not possible with pure CSS, because (as you have already indicated), when we add an additional transformation rule to an element that already has a transformation, the whole transformation gets reset, because it overwrites and does not add to the existing transformation.

With JS this could be achieved, but even there it will be difficult, because we must do the following:

  • Handle the animationend event upon completion of the first animation
  • In the handler, get translateX(...) in pixels.
  • Get CSS keyframe rules for the next animation, change them to translateX(...) as the first part of the conversion stack.

Note: I assume that you have a case where you absolutely cannot use the first method mentioned in the question.


An alternative method to achieve a similar effect would be to animate the margin or position element instead of using transform: translate() . One of the main drawbacks of this approach is that it will not be done at the GPU level (as opposed to transform ) and, therefore, will be slower when several such animations occur simultaneously (and can also be expensive). A.

Using fields:

Below the fragment achieves the effect, reviving the margin-left and margin-top properties.

 .animation-1, .animation-2, .animation-3 { width: 200px; height: 200px; display: inline-block; background: white; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); vertical-align: middle; } .movable-1, .movable-2, .movable-3 { background: #41A186; width: 50px; height: 50px; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); text-align: center; vertical-align: middle; line-height: 50px; } .movable-1 { animation-name: move1; animation-duration: 4s; animation-delay: 0s; animation-fill-mode: forwards; } .movable-2 { animation-name: move2-right, move2-down; animation-duration: 2s, 2s; animation-delay: 4s, 6s; animation-fill-mode: forwards, forwards; animation-timing-function: linear; } .movable-3 { animation-name: move3-diagonal; animation-duration: 4s; animation-delay: 8s; animation-fill-mode: forwards; animation-timing-function: linear; } @keyframes move1 { 0% { transform: translateX(0px); } 50% { transform: translateX(30px); } 100% { transform: translateX(30px) translateY(50px); } } @keyframes move2-right { 0% { margin-left: 0px; } 100% { margin-left: 30px; } } @keyframes move2-down { 0% { margin-top: 0px; } 100% { margin-top: 50px; } } @keyframes move3-diagonal { 0% { margin-top: 0px; margin-left: 0px; } 100% { margin-top: 50px; margin-left: 30px; } } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <div class="animation-1"> <div class="movable-1">1</div> </div> <div class="animation-2"> <div class="movable-2">2</div> </div> <div class="animation-3"> <div class="movable-3">3</div> </div> 

Use position:

This snippet provides the same effect using the animation properties left and top . The child element has position: absolute .

 .animation-1, .animation-2, .animation-3 { width: 200px; height: 200px; display: inline-block; background: white; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); position: relative; } .movable-1, .movable-2, .movable-3 { background: #41A186; width: 50px; height: 50px; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); text-align: center; vertical-align: middle; line-height: 50px; position: absolute; } .movable-1 { animation-name: move1; animation-duration: 4s; animation-delay: 0s; animation-fill-mode: forwards; } .movable-2 { animation-name: move2-right, move2-down; animation-duration: 2s, 2s; animation-delay: 4s, 6s; animation-fill-mode: forwards, forwards; animation-timing-function: linear; } .movable-3 { animation-name: move3-diagonal; animation-duration: 4s; animation-delay: 8s; animation-fill-mode: forwards; animation-timing-function: linear; } @keyframes move1 { 0% { transform: translateX(0px); } 50% { transform: translateX(30px); } 100% { transform: translateX(30px) translateY(50px); } } @keyframes move2-right { 0% { left: 0px; } 100% { left: 30px; } } @keyframes move2-down { 0% { top: 0px; } 100% { top: 50px; } } @keyframes move3-diagonal { 0% { top: 0px; left: 0px; } 100% { top: 50px; left: 30px; } } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <div class="animation-1"> <div class="movable-1">1</div> </div> <div class="animation-2"> <div class="movable-2">2</div> </div> <div class="animation-3"> <div class="movable-3">3</div> </div> 

Note: As described in my answer here , you can of course add a wrapper element and set the animation to move it down. This would give the same effect as the first, but I do not propose this approach, because it is against the very point of your question (which, in my opinion, was how to add several animations to the same element and make a second start with the first place is over).

 .animation-1, .animation-2 { width: 200px; height: 200px; display: inline-block; background: white; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } .movable-1, .movable-2 { background: #41A186; width: 50px; height: 50px; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); text-align: center; vertical-align: middle; line-height: 50px; } .movable-1 { animation-name: move1; animation-duration: 4s; animation-delay: 0s; animation-fill-mode: forwards; } .movable-2 { animation-name: move2-right; animation-duration: 2s; animation-delay: 4s; animation-fill-mode: forwards; } .movable-2-wrapper { animation-name: move2-down; animation-duration: 2s; animation-delay: 6s; animation-fill-mode: forwards; } @keyframes move1 { 0% { transform: translateX(0px); } 50% { transform: translateX(30px); } 100% { transform: translateX(30px) translateY(50px); } } @keyframes move2-right { 0% { transform: translateX(0px); } 50% { transform: translateX(30px); } 100% { transform: translateX(30px); } } @keyframes move2-down { 0% { transform: translateY(0px); } 50% { transform: translateY(50px); } 100% { transform: translateY(50px); } } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <div class="animation-1"> <div class="movable-1">1</div> </div> <div class="animation-2"> <div class='movable-2-wrapper'> <div class="movable-2">2</div> </div> </div> 
+4
source share

All Articles