Css animation - how to do multi step animation?


#1

Hi,
so i've not used css animation before but i want to create a multistep animation. I've been looking at https://www.w3schools.com/css/css3_animations.asp and it shows the basic idea but i am not sure how to step to the next animation.

I want to be able to have 5 images that show in turn but each image will grow in size and then disappear quickly and then the next image appear and again grow. The it will end with nothing showing. Basically a countdown

I'm unsure what is the best way of doing that. Do i have 1 set of keyframes and use percentages to go from one part to the next OR do i create different keyframe sets that run 1 after the other (or timed to do so).

This is as far as i have got. But as above i am not sure this is the correct way to proceed. Any pointers would be useful. thanks

<!DOCTYPE html>
<html>
<head>
<style> 
div {
    width: 100px;
    height: 100px;
    background-color: red;
    
    background-size: cover;
    -webkit-animation-name: example; /* Safari 4.0 - 8.0 */
    -webkit-animation-duration: 4s; /* Safari 4.0 - 8.0 */
    animation-name: example;
    animation-duration: 6s;
    -webkit-animation-name: example; /* Safari 4.0 - 8.0 */
    -webkit-animation-duration: example 6s; /* Safari 4.0 - 8.0 */
    animation-name: example;
    animation-duration: example 6s;
     
}

/* Safari 4.0 - 8.0 */
@-webkit-keyframes example {
    from {background-color: red; background-size:cover;background: transparent url('https://png.icons8.com/ios/540/black-cat-filled.png') center center no-repeat;}
    to {background-color: yellow;background-size:200px;width:200px;height:200px;background: transparent url('https://png.icons8.com/ios/540/black-cat-filled.png') center center no-repeat;}
}
/* Standard syntax */
@keyframes example {
    0% {background-color: red;background-size:cover;background: transparent url('https://png.icons8.com/ios/540/black-cat-filled.png') center center no-repeat;}
    100% {background-color: yellow;background-size:200px;width:200px;height:200px;background: transparent url('https://png.icons8.com/ios/540/black-cat-filled.png') center center no-repeat;}
    
}
 
</style>
</head>
<body>
<div></div>
</body>
</html>

#2

Hi,
I was able to put together an example that does most of what you wanted.

It's best to group as many styles together as you can and then just apply the changes through the progressions.

One problem I foresee with the BG images is that the browser only loads them as they are needed. My attempt to resolve that is to load them all on the parent as multiple bg images. Then add some extra time to the animation-delay, I set the delay at 4s so it takes four seconds before animation begins. This might work for fast connections but still might cause delays for people on slower connections.

It might be best to preload all the images with another method.

However this example should still work along with another preloading method. I'm just swapping out background sizes as they step through the animations.

I'm sure there are other ways to do it, but this should get you started.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Swap Out BG Images Animation</title>
<style>
div {
   width: 100px;
   height: 100px;
   background-color: red;
   background-image:
      url(https://png.icons8.com/ios/540/pig-filled.png),
      url(https://png.icons8.com/ios/540/cat-filled.png),
      url(https://png.icons8.com/ios/540/bull-filled.png),
      url(https://png.icons8.com/ios/540/chicken-filled.png);
   background-repeat: no-repeat;
   background-size: 0px, 0px, 0px, 0px;
   background-position: 100%;
   animation: example 8s linear 4s;  /*name/duration/timing-function/delay*/
}

@keyframes example {
   0% {
      background-size: cover, 0px, 0px, 0px;
      background-color: green;
      width:150px;
      height:150px;
   }
   25% {
      background-size: 0px, cover, 0px, 0px;
      background-color: red;
      width:200px;
      height:200px;
   }
   50% {
      background-size: 0px, 0px, cover, 0px;
      background-color: blue;
      width:250px;
      height:250px;
   }
   100% {
      background-size: 0px, 0px, 0px, cover;
      background-color: yellow;
      width:300px;
      height:300px;
   }
}
</style>
</head>
<body>
   <div></div>
</body>
</html>

#3

I don't have time to go into code at the moment. But conceptually this can be done with little math and management.

You said you wanted FIVE images working as a countdown.
This means you have 5 images.
you can set an animation on ALL 5 images.
then use the animation-delay property on EACH INDIVIDUAL IMAGE. Set the duration of the deal on each image as follows: (image # -1)* length of animation. This will ensure the animations "run" after the previous animations finish.
You probably want to make sure all animations end with the element being hidden.

hope that helps


#4

Just curious... how would you keep the images from layering on top each other 'with little math and management' ?

I mean whether an element animates or not, and it has multiple bg images...those images must at least be positioned to manage the natural layering that happens.

Then in the case of a fixed size box that has them swapping out (trading positions) during the animation, there must be more to it than individual animation-delay.

A code example of the concept your explaining would be most helpful when time allows.


#5

The image WOULD stack on each other. But only one would be visible at a time.
for this you could use display: none; ( or absolute positioning) to control the order of the stack.

I mean whether an element animates or not, and it has multiple bg images...those images must at least be positioned to manage the natural layering that happens.

that's where my solution and yours differed. I didn't have one shell with multiple BG. I was suggesting using multiple IMG tags within a container.


#6

Okay I see how that would work then, I was working from Noppy's example using bg images.

Is there a way to use steps() , as in steps(5, end) and have it target the animation changes using

from - to - to - to - to

rather than using
0% - 25% - 50% -75% -100%

Or do you only get one instance of from - to

@keyframes example {
 from { }
  to { }
}

#7

Here is a quick demo:

<!doctype html>


<html>
	<head>
		<title> </title>
	</head>
	<style type="text/css" media="screen">
		.demo{
			width: 120px;
			height: 120px;
 			border: 1px solid;
			text-align: center;
			
		}
		.demo:before{
			 /* 
				 quick and dirty centering technique... not part of demo
				 presented only a little challenge because my sample images
				 were not proportional to each other; expect this would not be the case in the actual implimentations
			*/
 			width: 1px;
			height: 100%;
 			content: '';
 			display: inline-block;
 			margin-left:-1.1em;
 			vertical-align: middle;
			
		}
		/* the magic*/
		.demo img{
			width: 0;
			display: none;
			vertical-align: middle;
  			animation-name: anim;
			animation-duration: 6s;
			animation-delay: 0s;
			display: inline-block;
		}
/* MATHS: delay= (img count -1) * 6s*/
 		.demo img+img{
   			animation-delay: 6s;
		}
 		.demo img+img+img{
   			animation-delay: 12s;
		}
 		.demo img+img+img+img{
   			animation-delay: 18s;
		}
		
@keyframes anim {
   0% { width:0;  }
  50% { width:100%;  }
  100% { width:0;  display: none; }
}		
	</style>
	<body>
		<div class="demo">
			<img src="https://png.icons8.com/ios/540/pig-filled.png">
			<img src="https://png.icons8.com/ios/540/cat-filled.png">
			<img src="https://png.icons8.com/ios/540/bull-filled.png">
			<img src="https://png.icons8.com/ios/540/chicken-filled.png">
	     </div>
	</body>
</html>

#8

I see now that the keyword from = 0% and to = 100% and that they also work with % selectors listed in between them.

@keyframes example {
   from {
      background-size: cover, 0, 0, 0, 0;
   }
   25% {
      background-size: 0, cover, 0, 0, 0;
   }
   50% {
      background-size: 0, 0, cover, 0, 0;
   }
   75% {
      background-size: 0, 0, 0, cover, 0;
   }
   to {
      background-size: 0, 0, 0, 0, cover;
      width: 200px;
      height: 200px;
   }
}

#9

Humble refinement on Ray H.'s bg technique:

div {
   width: 100px;
   height: 100px;
   background-color: red;
   background-image:
      url(https://png.icons8.com/ios/540/pig-filled.png),
      url(https://png.icons8.com/ios/540/cat-filled.png),
      url(https://png.icons8.com/ios/540/bull-filled.png),
      url(https://png.icons8.com/ios/540/chicken-filled.png);
   background-repeat: no-repeat;
   background-size: 0,0,0,0;
   background-position: 50%;
   animation: example 8s linear 4s;  /*name/duration/timing-function/delay*/
}

@keyframes example {
   from {
      background-size: 0, 0, 0, 0;
   }
   12.5% {
      background-size: 100%, 0, 0, 0;
   }
   25% {
      background-size: 0, 0,0, 0;
   }
   37.5% {
      background-size: 0, 100%, 0, 0;
   }
   50% {
      background-size: 0, 0, 0, 0;
   }
   62.5% {
      background-size: 0, 0, 100%, 0;
   }
   75% {
      background-size: 0, 0, 0, 0;
   }
   87.5% {
      background-size: 0, 0, 0, 100%;
   }
   to {
      background-size: 0, 0, 0, 0%;
   }
}

#10

I'd use transform for smoother animation. Something like this:

You can also leave out the 0 and 100% keyframes to shorten the code to this.

.demo {
	width: 120px;
	height: 120px;
	border: 1px solid;
	position:relative;
    overflow:hidden;
}
.demo img {
	position:absolute;
	left:0;right:0;top:0;
	bottom:0;
	margin:auto;
	width: 120px;
	height:120px;
	overflow:hidden;
	transform:scale(0);
	animation: anim 6s;
}
/* MATHS: delay= (img count -1) * 6s*/
.demo img:nth-child(2) {animation-delay: 6s;}
.demo img:nth-child(3) {animation-delay: 12s;}
.demo img:nth-child(4) {animation-delay: 18s;}
@keyframes anim {
 50% {transform:scale(1);}
}

<div class="demo"> <img src="https://png.icons8.com/ios/540/pig-filled.png"> <img src="https://png.icons8.com/ios/540/cat-filled.png"> <img src="https://png.icons8.com/ios/540/bull-filled.png"> <img src="https://png.icons8.com/ios/540/chicken-filled.png"> </div>

Or quicker as a countdown using 5 images:

Note: Just edited the above pens for a slightly better method.


#11

WOW. Thanks all that is much appreciated. I will have a look through what you've all suggested to get up to speed how what and how you have implemented each bit.

I'll obviously need to do some testing across all devices but assuming that is all good i think that is exactly what i was looking to achieve.

thank you all so much


#12

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.