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>
Harry
source share