Loop a CSS3 animation - css

I'm trying to loop a css3 animation between 3 elements, after the 3rd element ends, I want to restart the animation and so on...
Here's my code:
.oferta-prods.run-animation img{
animation-name:fadeIn;
animation-duration:4s;
animation-timing-function:ease-in-out;
opacity:0;
}
.oferta-prods.run-animation img:nth-child(1){animation-delay:0s;}
.oferta-prods.run-animation img:nth-child(2){animation-delay:4s;}
.oferta-prods.run-animation img:nth-child(3){animation-delay:8s;}
#keyframes fadeIn{
0%{
opacity:0;
}
10%{
opacity:1;
}
90%{
opacity:1;
}
100%{
opacity:0;
}
}
<div class="oferta-prods run-animation">
<img src="assets/House.svg">
<img src="assets/Car.svg">
<img src="assets/Beach.svg">
</div>
So, the idea is, element 1 starts animation then ends, element 2 starts animation then ends, then element 3 starts animation then ends. After this, I want to automatically begin a new cycle after the 3 elements end the animation.
Thank you

You can do this by defining 3 diferent animations with different execution timers.
Following my coding example bellow, we divide 100% / 3, and that gives us around 33%, meaning, that every image should run the animation for 33% of the animation total time.
Take a look at this example:
ody {
margin: 0;
padding: 0;
box-sizing: border-box;
height: 100vh;
}
.animation-wrapper div {
width: 20px;
height: 50px;
margin: 10px;
}
.animation-wrapper .anim-1 {
background-color: red;
animation: animation1 4s infinite ease-in-out;
}
.animation-wrapper .anim-2 {
background-color: blue;
animation: animation2 4s infinite ease-in-out;
}
.animation-wrapper .anim-3 {
background-color: green;
animation: animation3 4s infinite ease-in-out;
}
#keyframes animation1{
0%{
transform: translateX(0);
}
16.5%{
transform: translateX(20px);
}
33%{
transform: translateX(0);
}
100%{
transform: translateX(0);
}
}
#keyframes animation2{
0%{
transform: translateX(0);
}
33%{
transform: translateX(0);
}
49.5%{
transform: translateX(20px);
}
66%{
transform: translateX(0);
}
100%{
transform: translateX(0);
}
}
#keyframes animation3{
0%{
transform: translateX(0);
}
66%{
transform: translateX(0);
}
82.5%{
transform: translateX(20px);
}
99%{
transform: translateX(0);
}
100%{
transform: translateX(0);
}
}
<div class="animation-wrapper">
<div class="anim-1"></div>
<div class="anim-2"></div>
<div class="anim-3"></div>
</div>

One way is to use Javascript to restart the animation. It involves triggering a DOM reflow, so it may not be the best way on a heavy page.
const lastImage = document.querySelector(".oferta-prods.run-animation img:nth-child(3)");
lastImage.addEventListener("animationend", () => {
lastImage.parentNode.classList.remove("run-animation");
void lastImage.offsetWidth; // trigger DOM reflow
lastImage.parentNode.classList.add("run-animation");
});
.oferta-prods.run-animation img {
animation: 4s ease-in-out fadeIn;
opacity: 0;
}
.oferta-prods.run-animation img:nth-child(1) { animation-delay: 0s; }
.oferta-prods.run-animation img:nth-child(2) { animation-delay: 4s; }
.oferta-prods.run-animation img:nth-child(3) { animation-delay: 8s; }
#keyframes fadeIn {
0% { opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% {opacity: 0; }
}
<div class="oferta-prods run-animation">
<img src="assets/House.svg">
<img src="assets/Car.svg">
<img src="assets/Beach.svg">
</div>

Related

How to make a smooth curve/rotate in a CSS animation

I am trying to create a CSS animation to make a plane take off from a runway and then make a slight curve to the right as it gains altitude. To accomplish this, I believe I need to adjust scale, rotation and x/y coordinates in the keyframes. I've been playing around with it for a while but I can't figure out how to make it look natural. What's the best way to calculate the various values I will need to make a smooth curve up and to the right?
.container {
width:700px;
height:100%;
}
img {
max-width:100%;
}
.airplane {
position:absolute;
bottom:0;
animation: takeoff linear 2s forwards;
}
#keyframes takeoff {
0% {
transform: translate(0,0) rotate(0);
}
5% {
transform: translate(0,0) rotate(0) scale(.9);
}
10% {
transform: translate(0,0) rotate(0) scale(.9);
}
20% {
transform:translate(0,0) rotate(0) scale(0.85);
}
30% {
transform:translate(0,0) rotate(0) scale(0.80);
}
40% {
transform:translate(0,0) rotate(0) scale(0.75);
}
50% {
transform:translate(0,0) rotate(5deg) scale(0.5);
}
60% {
transform:translate(0,0) rotate(5deg) scale(0.45);
}
70% {
transform: translate(150px, -200px) rotate(10deg) scale(.4);
}
80% {
transform:translate(200px,-300px) rotate(20deg) scale(0.35);
}
90% {
transform:translate(250px,-400px) rotate(30deg) scale(0.3);
}
100% {
transform:translate(300px,-500px) rotate(30deg) scale(0.3);
}
}
<div class="container">
<img class="airplane" src=https://i.stack.imgur.com/DhHSc.png" />
</div>
You can probably consider an animation on the container to make it easier to handle:
.container {
position: absolute;
bottom: 0;
animation: takeoff-alt ease-in 1s 1s forwards;
}
img {
max-width:100%;
}
.airplane {
animation: takeoff linear 2s forwards;
}
#keyframes takeoff {
to {
transform: scale(0.1);
}
}
#keyframes takeoff-alt {
100% {
transform: rotate(30deg) translateY(-100%);
}
}
body {
overflow:hidden;
}
<div class="container">
<img class="airplane" src="https://i.stack.imgur.com/DhHSc.png" />
</div>

#-webkit-keyframes clashing with others

I have a keyframe animation effect on 2 banners on my homepage. I have defined each banner to have a different class so I could choose a different speed for each animation. The HTML looks like this:
HTML
<div class="subpage-image-sca">
<span class="subpage-image ken-burns-container">
<img src="http://staging.morningsidepharm.com/wp/wp-content/uploads/2018/09/Header-Image-homepage-compressor.jpg" class="ken-burns-image">
</span>
</div>
<div class="subpage-image-sca">
<span class="subpage-image ken-burns-container-20">
<img src="http://staging.morningsidepharm.com/wp/wp-content/uploads/2018/09/Header-Image-homepage-compressor.jpg" class="ken-burns-image-20">
</span>
</div>
The CSS Code looks like this:
CSS
/* ------------ Ken Burns 10 Secs ------------- */
.ken-burns-container {
overflow: hidden;
}
.ken-burns-image {
width: 100%;
height: 100%;
background-size: cover;
background-clip: border-box;
animation: 10s ease-in 0s 1 scaleout;
-webkit-animation: 10s ease-in 0s 1 scaleout;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes scaleout {
0% { transform: scale(1); }
100% {transform: scale(20);
}
}
/* ------------ Ken Burns 20 Secs ------------- */
.ken-burns-container-20 {
overflow: hidden;
}
.ken-burns-image-20 {
width: 100%;
height: 100%;
background-size: cover;
background-clip: border-box;
animation: 20s ease-in 0s 1 scaleout;
-webkit-animation: 20s ease-in 0s 1 scaleout;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes scaleout {
0% { transform: scale(1); }
100% {transform: scale(1.17);
}
}
Heres a JS Fiddle: https://jsfiddle.net/shan_2000_uk/yhf4dzrx/10/
Both of these bits of CSS work fine on their own. It seems that there is a conflict with the last block of code that defines the scale:
#-webkit-keyframes scaleout {
0% { transform: scale(1); }
100% {transform: scale(20);
}
}
If I remove this block from either of the sections, the other works fine.
I have tried adding the class to this block like so:
.ken-burns-container-20 #-webkit-keyframes scaleout {
0% { transform: scale(1); }
100% {transform: scale(1.17);
}
}
But this doesn't seem to work.
Does anyone know, A: Why the code is conflicting and B: A way to use both bits of code without them conflicting?
Thanks a lot for taking the time to look!
You're just overriding the first #keyframe rule with the last one, you'll probably need to name them with different names, let's scaleout1 for the first #keyframe and scaleout2 for the last #keyframe.
Here's a demo:
.ken-burns-container, .ken-burns-container-20 {
overflow: hidden;
}
.ken-burns-image {
width: 100%;
height: 100%;
background-size: cover;
background-clip: border-box;
animation: scaleout1 10s ease-in;
animation-fill-mode: forwards;
}
.ken-burns-image-20 {
width: 100%;
height: 100%;
background-size: cover;
background-clip: border-box;
animation: scaleout2 20s ease-in;
animation-fill-mode: forwards;
}
/* keyframes */
#keyframes scaleout1 {
0% { transform: scale(1); }
100% { transform: scale(20); }
}
#keyframes scaleout2 {
0% { transform: scale(1); }
100% { transform: scale(1.17); }
}
<div class="subpage-image-sca">
<span class="subpage-image ken-burns-container">
<img src="https://via.placeholder.com/300x300" class="ken-burns-image">
</span>
</div>
<div class="subpage-image-sca">
<span class="subpage-image ken-burns-container-20">
<img src="https://via.placeholder.com/500x500" class="ken-burns-image-20">
</span>
</div>
Hope I pushed you further.

Two separate CSS animations doing the same thing

I'm setting up some predefined animation classes to animate on scroll. They all work, except one I've called slideUp, which seems to behave exactly like slideDown. The animations look exactly like they sound, and are using transforms like so:
#keyframes slideUp {
from {
-webkit-transform: translateY(10%);
transform: translateY(10%);
}
to {
-webkit-transform: translateY(0%);
transform: translateY(0%);
}
}
#keyframes slideDown {
from {
-webkit-transform: translateY(-10%);
transform: translateY(-10%);
}
to {
-webkit-transform: translateY(0);
transform: translateY(0);
}
}
Seems that no matter what, calling slideUp generates an animation that looks like slideDown, and I can't see any error in my keyframes, nor in execution.
Example of execution:
animation: slideUp 600ms $transition-ease-in 1 forwards, fadeIn 500ms linear 1 forwards;
Thanks!
Edit: I changed the name slideUp to slideup and it started working. This is a from-scratch project, so I can guarantee no conflicts in my code that would have caused that. Any ideas?
Here is an example that may help you. I made it with your animation. Hope this will help. https://jsfiddle.net/ssr3axtr/2/
html :
<div class="box box--1">
</div>
<div class="box box--2">
</div>
CSS :
#keyframes slideUp {
from {
-webkit-transform: translateY(10%);
transform: translateY(10%);
}
to {
-webkit-transform: translateY(0%);
transform: translateY(0%);
}
}
#keyframes slideDown {
from {
-webkit-transform: translateY(-10%);
transform: translateY(-10%);
}
to {
-webkit-transform: translateY(0);
transform: translateY(0);
}
}
.box{
display:inline-block;
width:50px;
height:50px;
background:blue;
transform:translateY(0);
}
.box--1{
animation: slideUp 1s linear 0s infinite forwards;
}
.box--2{
animation: slideDown 1s linear 0s infinite forwards;
}
I think your animation shorthand lists properties in the wrong order. Try this:
#keyframes slideUp {
from {
-webkit-transform: translateY(10%);
transform: translateY(10%);
}
to {
-webkit-transform: translateY(0%);
transform: translateY(0%);
}
}
#keyframes slideDown {
from {
-webkit-transform: translateY(-10%);
transform: translateY(-10%);
}
to {
-webkit-transform: translateY(0);
transform: translateY(0);
}
}
.btn {
background: green;
color: white;
padding: 2em;
display: inline-block;
animation: 600ms cubic-bezier(0.1, 0.7, 1.0, 0.1) 1 forwards slideUp;
}
<div class="btn">button</div>

Spinning an image using rotateY

I'd like to spin an image and I came across this video https://www.youtube.com/watch?v=nD8xqlh6Esk which gave a very simple way to spin a div on a click. I thought this would be a great method to spin an image on a page load with minimal css so tried using a :after as opposed to a :click (with 720 deg) but that didn't work. Has anyone got this approach to work on a page load rather than on a click? I've seen other methods but they need quite a bit more css.
Detail provided
[Apparently my youtube link is to a football match although for me it's to a LevelUp Tuts CSS Experiments #1 - Card Flipping Effect video.]
Basically, he flips a card through a simple transform on a hover as follows:
<div class="card"></div>
.card {
background: blue;
width: 200px;
height: 200px;
}
.card:hover {
transform: rotateY (90deg);
}
So you can spin the div with a single line, a transform, on a hover. There's no need for keyframes.
Try this:
div {
width: 100px;
height: 100px;
background: red;
animation: spin 2s infinite;
-webkit-animation: spin 2s infinite;
}
#keyframes spin{
to{
transform: rotate(360deg);
}
}
#-webkit-keyframes spin{
to{
transform: rotate(360deg);
}
<div id="d"></div>
EDIT: is this more like what you wanted?
div {
width: 100px;
height: 100px;
background: red;
animation: spin 2s forwards;
-webkit-animation: spin 2s forwards;
}
#keyframes spin{
to{
transform: rotateY(90deg);
}
}
#-webkit-keyframes spin{
to{
transform: rotateY(90deg);
}
}
<div id="d"><img src="http://img4.wikia.nocookie.net/__cb20120208185721/logopedia/images/5/54/Barclays_Premier_League_logo_(shield).gif" width="100px" height="100px"></div>
You need animation as well, not just transition:
http://jsfiddle.net/rudiedirkx/AB277/95/
The magic:
.card {
animation: spinn 5s linear infinite;
/* you don't need transition at all */
}
#keyframes spinn {
0% { transform: rotateY(0deg); }
100% { transform: rotateY(720deg); }
}
For some reason, Chrome still needs prefixes.
More info on css-tricks.
this animates the object as soon as the css and the html load:
(http://jsfiddle.net/oemtt7cr/)
#-webkit-keyframes spin {
from {
-webkit-transform: rotateY(0deg);
}
to {
-webkit-transform: rotateY(720deg);
}
}
#keyframes spin {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(720deg);
}
}
.container {
-webkit-perspective: 2000px;
}
.card {
margin: 20px;
background: #990;
width: 200px;
height: 200px;
animation: spin 5s ease;
-webkit-animation: spin 5s ease;
}
<div class="container">
<div class="card">flipy</div>
</div>
Use .card:hover instead of .card:after if you like the animation start when user move in with cursor.
http://jsfiddle.net/AB277/90/
.card {margin 20px;
background: blue;
width: 200px;
height:200px;
transition: all 5s;
}
.card:hover {
transform: rotateY(720deg);
}
Or if you like the animation at page load, use the following script.
http://jsfiddle.net/AB277/93/
<div id="card"
</div>
var elm = document.getElementById('card');
elm.classList.add('cardMove');
#card {margin 20px;
background: blue;
width: 200px;
height:200px;
transition: all 5s;
}
.cardMove {
transform: rotateY(720deg);
}

CSS3 Animation to hoverstate and back

I need an element that initially has no animation, then animates to a different state on hover (one time, no loop) and after the hover is gone it should animate back to its original state.
Basically just like you would do it with a :hover style and a transition.
Is there a way to achieve that with a CSS3 animation?
This is my current usecase: http://jsfiddle.net/yjD73/11/
On hover an element fades from opacity: 0 to opacity: 1 and back.
This is what i think is not possible with transitions.
EDIT: As requested here the exact code from jsfiddle
a div with four images
<div class="zoombox">
<img src="http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=4&center=51.561998,-1.605100">
<img src="http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=7&center=51.561998,-1.605100">
<img src="http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=12&center=51.561998,-1.605100">
<img src="http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=16&center=51.562606,-1.605100">
</div>
images stacked onto each other and simple css animations on hover
.zoombox {
position: relative;
margin: 50px;
float: left;
}
/* initial state */
.zoombox img:not(:first-child) {
position: absolute;
top: 0;
opacity: 0;
}
/* On hover in */
.zoombox:hover img:nth-child(1) {
-webkit-animation: first-in 400ms 0ms 1 normal ease-in both;
}
.zoombox:hover img:nth-child(2) {
-webkit-animation: middle-in 1600ms 0ms 1 linear both;
}
.zoombox:hover img:nth-child(3) {
-webkit-animation: middle-in 1600ms 1200ms 1 linear both;
}
.zoombox:hover img:nth-child(4) {
-webkit-animation: last-in 400ms 2400ms 1 linear both;
}
#-webkit-keyframes first-in {
0% {
-webkit-transform: scale(1);
opacity: 1;
}
100% {
-webkit-transform: scale(1.5);
opacity: 0;
}
}
#-webkit-keyframes middle-in {
0% {
-webkit-transform: scale(0.5);
opacity: 0;
}
25%, 75% {
-webkit-transform: scale(1);
opacity: 1;
}
100% {
-webkit-transform: scale(1.5);
opacity: 0;
}
}
#-webkit-keyframes last-in {
0% {
-webkit-transform: scale(0.5);
opacity: 0;
}
100% {
-webkit-transform: scale(1);
opacity: 1;
}
}
Conic, I have created a JSFiddle that replicates most of what you want with css3 animations.
Here it is.
The code that makes this all possible in CSS is:
#-webkit-keyframes changeImage {
0% {background: url("http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=4&center=51.561998,-1.605100");}
33% {background: url("http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=7&center=51.561998,-1.605100");}
67% {background: url("http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=12&center=51.561998,-1.605100");}
100% {background: url("http://maps.googleapis.com/maps/api/staticmap?sensor=false&size=300x300&maptype=hybrid&zoom=16&center=51.562606,-1.605100");}
}
Right now the jsfiddle is having the image run through the animation on hover and return to the original image. Let me know if you need any over things to happen and by the way, this won't work on any touch devices as a result of a lack of hover state possibilities.

Resources