I am using keyframes but my h1 is not visible on button click. What am I doing wrong?
Here is my code:
function abc() {
document.querySelector('.h1cls').classList.add('fadeIn')
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation-name: fadeIn;
animation-duration: 150ms;
animation-timing-function: linear;
animation-delay: 5000ms;
/*opacity:1;*/
}
.one .two .h1cls {
opacity: 0;
}
<div class="one">
<div class="two">
<h1 class="h1cls">hello</h1>
<div></div>
</div>
</div>
<button onclick="abc()">asd</button>
https://codesandbox.io/s/serene-lamport-12kgz?file=/index.html:0-994
actually I am using opacity . I am setting opacity to 1 after button click.
In your abc() function, you should also remove h1cls class due to the fact that it still applies opacity: 0 style.
function abc(){
document.querySelector('.h1cls').classList.add('fadeIn')
document.querySelector('.h1cls').classList.remove('h1cls')
}
It is animating but then disappearing immediately. You need to tell the system to keep the final state of the animation. You do this with animation-fill-mode: forwards
Note that the animation will only run on the first click of the button.
You have to add animation-fill-mode:forwards; property too in the fadeClass in order to make this work
function abc() {
document.querySelector('.h1cls').classList.add('fadeIn')
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation-name: fadeIn;
animation-duration: 150ms;
animation-timing-function: linear;
/*animation-delay: 5000ms;*/
animation-fill-mode:forwards; // add this line
/*opacity:1;*/
}
.one .two .h1cls {
opacity: 0;
}
<div class="one">
<div class="two">
<h1 class="h1cls">hello</h1>
<div></div>
<button onclick="abc()">asd</button>
you can used the toggle class and transition
function abc() {
document.querySelector('.h1cls').classList.toggle('fadeIn')
}
.one .two .h1cls {
transition: opacity 150ms linear;
opacity: 0;
}
.one .two .h1cls.fadeIn {
opacity:1;
}
<div class="one">
<div class="two">
<h1 class="h1cls">hello</h1>
<div></div>
<button onclick="abc()">asd</button>
</div>
</div>
or with animation
function abc() {
document.querySelector('.h1cls').classList.toggle('fadeIn')
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.one .two .h1cls {
opacity: 0;
}
.one .two .h1cls.fadeIn {
animation-name: fadeIn;
animation-duration: 150ms;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
<div class="one">
<div class="two">
<h1 class="h1cls">hello</h1>
<div></div>
<button onclick="abc()">asd</button>
</div>
</div>
You've missed animation-fill-mode property in fadeIn CSS class.
Correct code:
.fadeIn {
animation-name: fadeIn;
animation-duration: 150ms;
animation-timing-function: linear;
animation-delay: 5000ms;
animation-fill-mode: forwards;
}
Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode
When we click on button it just adding class fadeIn and this class will animate from opacity 0 to opacity 1. But after animation completed it will again hide, so add opacity:1!important in .fadeIn class property.
In simple way just add opacity:1!important in fadeIn css property.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Static Template</title>
<style>
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation-name: fadeIn;
animation-duration: 150ms;
animation-timing-function: linear;
animation-delay: 5000ms;
opacity:1 !important;
}
.one .two .h1cls {
opacity: 0;
}
</style>
</head>
<body>
<div class="one">
<div class="two">
<h1 class="h1cls">hello</h1>
<div>
</div>
<button onclick="abc()">asd</button>
<script>
function abc(){
document.querySelector('.h1cls').classList.add('fadeIn')
}
</script>
</body>
</html>
Related
I have a heading <h1>I am Heading</h1> with animation properties and I want to display my <p>I am Paragraph</p> to display after heading fully loaded
Attach an animationend event listener to the h1 that shows the paragraph element in 5000 milliseconds with setTimeout:
const heading = document.querySelector('h1');
const paragraph = document.querySelector('p');
heading.addEventListener('animationend', function() {
console.log('showing paragraph in 5 seconds')
setTimeout(() => {
paragraph.style.display = "block"
}, 5000)
})
h1 {
animation: fadeIn 2s forwards;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
p {
display: none;
}
<h1>I am Heading</h1>
<p>I am Paragraph</p>
Try this. setTimeout() method can execute a piece of code after a certain amount of time has passed.
<!DOCTYPE html>
<html>
<head>
<title>CSS</title>
</head>
<body>
<h1>Hello</h1>
<p id="para">Hey this is saruque</p>
<style>
#keyframes show {
from{
opacity: 0;
}
to{
opacity: 1;
}
}
h1{
animation: show 5s forwards;
}
#para{
visibility: hidden;
}
</style>
<script>
setTimeout(function(params) {
document.getElementById('para').style.visibility = 'visible'
}, 5200);
</script>
</body>
</html>
You can add a delay to your animation:
p {
opacity: 0;
animation-name: fadeIn;
animation-duration: .4s;
animation-fill-mode: forwards;
animation-delay: 5s;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
I want to create simple text animation. When i click a button, text shifts from fully transparent to fully visible and reverts to transparent. I wrote code that does the animation but only once. The animation doesn't work anymore every time when i click the button:
function animation() {
$("span").removeClass("opacity-effect");
$("span").addClass("opacity-effect");
}
span{
opacity: 0;
}
.opacity-effect {
animation-name: animate-opacity-effect;
animation-duration: 1400ms;
animation-fill-mode: forwards;
opacity: 0;
}
#keyframes animate-opacity-effect {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>Hello World!</span>
<button onClick="animation()">
Start animation
</button>
The animation does not repeat, because for animation to start CSS requires a frame when there was no class.
So, to solve this, you should delay adding class to the next frame
function animation() {
$("span").removeClass("opacity-effect");
requestAnimationFrame(()=>{
$("span").addClass("opacity-effect");
});
}
You need to reset the animation. There is a good and correct way to do this, using event animationend. In this event, you need to put the removal of the class opacity-effect.
function animation() {
$("span").addClass("opacity-effect");
$("span").on("animationend", function() {
$(this).removeClass("opacity-effect");
});
}
span {
opacity: 0;
}
.opacity-effect {
animation-name: animate-opacity-effect;
animation-duration: 1400ms;
animation-fill-mode: forwards;
opacity: 0;
}
#keyframes animate-opacity-effect {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>Hello World!</span>
<button onClick="animation()">
Start animation
</button>
You need to add a small delay between the removeClass and the addClass. This can be done in two ways:
With a setTimeout
function animation() {
$("span").removeClass("opacity-effect")
setTimeout(() => {
$("span").addClass("opacity-effect");
}, 0);
}
span{
opacity: 0;
}
.opacity-effect {
animation-name: animate-opacity-effect;
animation-duration: 1400ms;
animation-fill-mode: forwards;
}
#keyframes animate-opacity-effect {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>Hello World!</span>
<button onClick="animation()">
Start animation
</button>
With a cloning
function animation() {
const newEl = $("span").removeClass("opacity-effect").clone(true);
$("span").before(newEl);
$("span:last").remove();
newEl.addClass("opacity-effect");
}
span{
opacity: 0;
}
.opacity-effect {
animation-name: animate-opacity-effect;
animation-duration: 1400ms;
animation-fill-mode: forwards;
}
#keyframes animate-opacity-effect {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span>Hello World!</span>
<button onClick="animation()">
Start animation
</button>
$('span').addClass('opacity-effect');
setTimeout(function(){
$('span').removeClass('opacity-effect');
}, 1400);
Try this
1400 is your animation duration time
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dropdown value from database</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
span{
opacity: 0;
}
.opacity-effect {
opacity: 0;
-webkit-animation: animate-opacity-effect 1400ms infinite;
-moz-animation: animate-opacity-effect 1400ms infinite;
-o-animation: animate-opacity-effect 1400ms infinite;
animation: animate-opacity-effect 1400ms infinite;
}
#keyframes animate-opacity-effect {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
#-o-keyframes animate-opacity-effect {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
#-moz-keyframes animate-opacity-effect {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
#-webkit-keyframes animate-opacity-effect {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
</style>
</head>
<body>
<span>Hello World!</span>
<button onClick="animation()">
Start animation
</button>
<script>
function animation() {
$("span").removeClass("opacity-effect");
$("span").addClass("opacity-effect");
}
</script>
</body>
</html>
I want to make a headline on my website which would animate like one on this website: https://www.thisisbeyond.com/what-we-believe/
So I want the words to fade-up each with a little delay.
How could I do that? If it is possible with css only, that would be great. But javascript is also acceptable :)
I have tried splitting my words each into one column and then animating the columns (opacity: 0 to 1 transition), but it results in strange spacing between words AND I want them to fade-up, not only change the opacity. So I think the right way to do it is by just putting each word in a different span element and then animating the spans.
<h1 class="animated2">
<span>To</span> <span>show</span> <span>the</span> <span>power</span> <span>of</span>
<span class="highlight">humanity </span>
<span class="highlight">in</span>
<span class="highlight">business.</span>
</h1>
LINK to the website I am trying to achieve this: michalkuczek.pl
.highlight{
background: #fff;
}
#keyframes fadeInUpSmall{
0%{
opacity:0;
transform:translateY(10px)}
100%{
opacity:1;
transform:translateY(0)}
}
.animated2 span:nth-child(1) {
animation-delay: .1s;
}
.animated2 span {
animation-name: fadeInUpSmall;
}
.animated2 {
animation-duration: 1s;
animation-fill-mode: both;
animation-fill-mode: both;
}
You can achieve the opacity animation by creating keyframes that define the start and end states.
CSS:
#-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
#-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
#keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
.fade-in {
opacity:0; /* make things invisible upon start */
-webkit-animation:fadeIn ease-in 1; /* call our keyframe named fadeIn, use animattion ease-in and repeat it only 1 time */
-moz-animation:fadeIn ease-in 1;
animation:fadeIn ease-in 1;
-webkit-animation-fill-mode:forwards; /* this makes sure that after animation is done we remain at the last keyframe value (opacity: 1)*/
-moz-animation-fill-mode:forwards;
animation-fill-mode:forwards;
-webkit-animation-duration:1s;
-moz-animation-duration:1s;
animation-duration:1s;
}
.fade-in.one {
-webkit-animation-delay: 0.7s;
-moz-animation-delay: 0.7s;
animation-delay: 0.7s;
}
.fade-in.two {
-webkit-animation-delay: 1.2s;
-moz-animation-delay:1.2s;
animation-delay: 1.2s;
}
.fade-in.three {
-webkit-animation-delay: 1.6s;
-moz-animation-delay: 1.6s;
animation-delay: 1.6s;
}
HTML:
<h1 class="animated2">
<span>To</span> <span>show</span> <span>the</span> <span>power</span> <span>of</span>
<span class="highlight fade-in one">humanity </span>
<span class="highlight fade-in two">in</span>
<span class="highlight fade-in three">business.</span>
</h1>
I'm making this site that plays our school hymn when the button "Play" is pressed and pauses when "Pause" is pressed. Alongside it the highlight animation 'per line' of the lyrics. However, I can't globally pause the animation. I wanted to pause the audio and the css animation but only the audio is the one that is actually paused so when I click the play button, the lyrics highlight and audio is not in sync anymore.
I've tried playing with animation-play-state in CSS but none of it worked great
Sorry if the code is long because I did 'per-line' lyrics but what I wanted to do is to pause any animations so that it is still in sync with the audio whenever I resume it.
.lyrics {
font-weight: lighter;
font-size: 1vw;
}
.l1.an {
animation: tae 1s;
animation-direction: alternate;
animation-duration: 5s;
animation-delay: 12s;
}
.l2.an {
animation: tae 1s;
animation-duration: 5s;
animation-fill-mode: alternate;
animation-delay: 15s;
}
.l3.an {
animation: tae 1s;
animation-duration: 8s;
animation-fill-mode: alternate;
animation-delay: 18s;
}
.l4.an {
animation: tae 1s;
animation-duration: 7s;
animation-fill-mode: alternate;
animation-delay: 24s;
}
.l5.an {
animation: tae 1s;
animation-duration: 8s;
animation-fill-mode: alternate;
animation-delay: 29s;
}
#keyframes tae {
0% {background: initial;}
30% {background: blue;}
60% {background: blue;}
100% {background: initial;}
}
<body>
<audio id="ad">
<source src = "pup.mp3" type="audio/mp3">
</audio>
<script type="text/javascript">
var song = document.getElementById("ad");
function togglePlay() {
song.play();
document.getElementByClassName("an").style.animationPlayState = "running"; //this is what I'm currently using in play button
}
function togglePause() {
song.pause();
document.getElementByClassName("an").style.animationPlayState = "paused"; //this is for the pause button
}
</script>
<div class="bg"></div>
<div class="bg-box">
<img src="PUPLogo.png">
<p class="PUP">Polytechnic University of the Philippines</p>
<h1>PUP HYMN</h1>
<p class="lyrics">
<div class="l1 an">Sintang Paaralan</div>
<div class="l2 an">Tanglaw ka ng bayan</div>
<div class="l3 an">Pandayan ng isip ng kabataan</div>
<div class="l4 an">Kami ay dumating nang salat sa yaman<br></div>
<div class="l5 an">Hanap na dunong ay iyong alay<br></div>
<!--I cut the lyrics here to make it shorter-->
<input type="button" value="Play" onclick="togglePlay()" class="but" ></input>
<input type="button" value="Pause" onclick="togglePause()" class="but"></input>
</div>
</body>
</html>
First there is type you need to use getElementsByClassName instead of getElementByClassName
The second note is that you have to loop through the elements when you select them by a class selector. So I wrote a loop on the elements with class "an":
var song = document.getElementById("ad");
function togglePlay() {
song.play();
Array.from(document.getElementsByClassName("an")).forEach(
function(element, index, array) {
element.style.animationPlayState = "running";
}
)
}
function togglePause() {
song.pause();
Array.from(document.getElementsByClassName("an")).forEach(
function(element, index, array) {
element.style.animationPlayState = "paused";
}
)
}
.lyrics {
font-weight: lighter;
font-size: 1vw;
}
.l1.an {
animation: tae 1s;
animation-direction: alternate;
animation-duration: 5s;
animation-delay: 12s;
}
.l2.an {
animation: tae 1s;
animation-duration: 5s;
animation-fill-mode: alternate;
animation-delay: 15s;
}
.l3.an {
animation: tae 1s;
animation-duration: 8s;
animation-fill-mode: alternate;
animation-delay: 18s;
}
.l4.an {
animation: tae 1s;
animation-duration: 7s;
animation-fill-mode: alternate;
animation-delay: 24s;
}
.l5.an {
animation: tae 1s;
animation-duration: 8s;
animation-fill-mode: alternate;
animation-delay: 29s;
}
#keyframes tae {
0% {background: initial;}
30% {background: blue;}
60% {background: blue;}
100% {background: initial;}
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="css1.css">
<meta charset="utf-8" content="width=device-width, initial-scale=1.0">
<meta http-equiv="refresh" content="106">
<title>PUP HYMN</title>
</head>
<body>
<audio id="ad">
<source src = "pup.mp3" type="audio/mp3">
</audio>
<div class="bg"></div>
<div class="bg-box">
<img src="PUPLogo.png">
<p class="PUP">Polytechnic University of the Philippines</p>
<h1>PUP HYMN</h1>
<p class="lyrics">
<div class="l1 an">Sintang Paaralan</div>
<div class="l2 an">Tanglaw ka ng bayan</div>
<div class="l3 an">Pandayan ng isip ng kabataan</div>
<div class="l4 an">Kami ay dumating nang salat sa yaman<br></div>
<div class="l5 an">Hanap na dunong ay iyong alay<br></div>
<!--I cut the lyrics here to make it shorter-->
<input type="button" value="Play" onclick="togglePlay()" class="but" ></input>
<input type="button" value="Pause" onclick="togglePause()" class="but"></input>
</div>
</body>
</html>
Use loop all of elemnt with class name an and set .style.animationPlayState to each one
also use getElementsByClassName() to get all elements with class name an
var song = document.getElementById("ad");
function togglePlay() {
song.play();
var items=document.getElementsByClassName("an");
for (var i=0; i < items.length; i++) {
items[i].style.animationPlayState = "running";
}
}
function togglePause() {
song.pause();
var items=document.getElementsByClassName("an");
for (var i=0; i < items.length; i++) {
items[i].style.animationPlayState = "paused";
}
}
.lyrics {
font-weight: lighter;
font-size: 1vw;
}
.l1.an {
animation: tae 1s;
animation-direction: alternate;
animation-duration: 5s;
animation-delay: 12s;
}
.l2.an {
animation: tae 1s;
animation-duration: 5s;
animation-fill-mode: alternate;
animation-delay: 15s;
}
.l3.an {
animation: tae 1s;
animation-duration: 8s;
animation-fill-mode: alternate;
animation-delay: 18s;
}
.l4.an {
animation: tae 1s;
animation-duration: 7s;
animation-fill-mode: alternate;
animation-delay: 24s;
}
.l5.an {
animation: tae 1s;
animation-duration: 8s;
animation-fill-mode: alternate;
animation-delay: 29s;
}
#keyframes tae {
0% {background: initial;}
30% {background: blue;}
60% {background: blue;}
100% {background: initial;}
}
<audio id="ad">
<source src = "pup.mp3" type="audio/mp3">
</audio>
<script type="text/javascript">
</script>
<div class="bg"></div>
<div class="bg-box">
<img src="PUPLogo.png">
<p class="PUP">Polytechnic University of the Philippines</p>
<h1>PUP HYMN</h1>
<p class="lyrics">
<div class="l1 an">Sintang Paaralan</div>
<div class="l2 an">Tanglaw ka ng bayan</div>
<div class="l3 an">Pandayan ng isip ng kabataan</div>
<div class="l4 an">Kami ay dumating nang salat sa yaman<br></div>
<div class="l5 an">Hanap na dunong ay iyong alay<br></div>
<!--I cut the lyrics here to make it shorter-->
<input type="button" value="Play" onclick="togglePlay()" class="but" />
<input type="button" value="Pause" onclick="togglePause()" class="but"/>
</div>
I have a CSS animation which is quite complex, ie. it's layered, or brings in two images, one a background image, then an <img> tag inside that, to overlay the original.
Demo is here: http://wdb.blazeoven.co.uk/
HTML:
<div class="container">
<a href="services.php">
<div class="col-sm-3 home-circle" id="one">
<img class="bottom" id="five" src="/assets/img/prop-consultants.png" alt="residential block in grounds">
</div>
</a>
<a href="services.php">
<div class="col-sm-3 home-circle" id="two">
<img class="bottom" id="six" src="/assets/img/chartered-surveyors.png" alt="old residential house doorways">
</div>
</a>
<a href="services.php">
<div class="col-sm-3 home-circle" id="three">
<img class="bottom" id="seven" src="/assets/img/managing-agents.png"
alt="row of shops">
</div>
</a>
<a href="services.php">
<div class="col-sm-3 home-circle" id="four">
<img class="bottom" id="eight" src="/assets/img/city-central.png" alt="City shop premises">
</div>
</a>
CSS:
#-webkit-keyframes fadeOut { from { opacity:1; } to { opacity:0; } }
#-moz-keyframes fadeOut { from { opacity:1; } to { opacity:0; } }
#keyframes fadeOut { from { opacity:1; } to { opacity:0; } }
#-webkit-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
#-moz-keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
#keyframes fadeIn { from { opacity:0; } to { opacity:1; } }
.home-banner .container a .col-sm-3 {
opacity:0;
-webkit-animation:fadeIn ease-in 1;
-moz-animation:fadeIn ease-in 1;
animation:fadeIn ease-in 1;
-webkit-animation-fill-mode:forwards;
-moz-animation-fill-mode:forwards;
animation-fill-mode:forwards;
-webkit-animation-duration:1s;
-moz-animation-duration:1s;
animation-duration:1s;
}
.home-banner #one {
background:url('/assets/img/propcons.svg') center no-repeat;
background-size: 100%;
-webkit-animation-delay: 0.4s;
-moz-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.home-banner #two {
background:url('/assets/img/charsurv.svg') center no-repeat;
background-size: 100%;
-webkit-animation-delay: 0.8s;
-moz-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.home-banner #three {
background:url('/assets/img/manage.svg') center no-repeat;
background-size: 100%;
-webkit-animation-delay: 1.4s;
-moz-animation-delay: 1.4s;
animation-delay: 1.4s;
}
.home-banner #four {
background:url('/assets/img/citycen.svg') center no-repeat;
background-size: 100%;
-webkit-animation-delay: 1.8s;
-moz-animation-delay: 1.8s;
animation-delay: 1.8s;
}
.grey-banner img.bottom {
opacity:1;
-webkit-animation:fadeOut ease-in 1;
-moz-animation:fadeOut ease-in 1;
animation:fadeOut ease-in 1;
// -webkit-animation-direction: alternate;
// -moz-animation-direction: alternate;
// animation-direction: alternate;
-webkit-animation-fill-mode:forwards;
-moz-animation-fill-mode:forwards;
animation-fill-mode:forwards;
-webkit-animation-duration:1s;
-moz-animation-duration:1s;
animation-duration:1s;
}
.grey-banner img#five {
-webkit-animation-delay: 6.8s;
-moz-animation-delay: 6.8s;
animation-delay: 6.8s;
}
.grey-banner img#six {
-webkit-animation-delay: 7.4s;
-moz-animation-delay: 7.4s;
animation-delay: 7.4s;
}
.grey-banner img#seven {
-webkit-animation-delay: 8s;
-moz-animation-delay: 8s;
animation-delay: 8s;
}
.grey-banner img#eight {
-webkit-animation-delay: 8.6s;
-moz-animation-delay: 8.6s;
animation-delay: 8.6s;
}
Trouble is, the client is requesting that it repeats again. That is, it plays in reverse, then starts again.
I have tried unsuccessfully to do this with CSS, is there a succinct way to do it with Javascript?
Thanks in advance for your comments.
Ben
You can repeat the animation using animation-iteration-count:
-moz-animation-iteration-count: 3; /* Firefox 5 -> 15 */
-webkit-animation-iteration-count: 3; /* Chrome, Safari, Opera */
animation-iteration-count: 3; /* Firefox 16, IE 10 */
Not supported in IE 9 and earlier.
You can also use the value infinite to repeat over and over.
Edit:
As I commented you can try with cubic-bezier:
Use no delay, and animation-duration:10s. You can try with these cubic-bezier values on the animation-timing-function for the four images:
animation-timing-function: cubic-bezier(0.2, 0.0, 0.0, 1.5);
animation-timing-function: cubic-bezier(0.4,-0.7, 0.4, 1.8);
animation-timing-function: cubic-bezier(0.7,-1.7, 0.7, 1.8);
animation-timing-function: cubic-bezier(0.9,-1.6, 0.8, 0.8);
I have not tried this myself, and I am not sure how well it works with the values that are < 0 and > 1 (which is not standard).
If you want to play around with how the cubic-bezier is set up, you can use the tool at http://cubic-bezier.com to help finding useful values.
You said the your client just wanted the animation to play normally, then play in reverse and then repeat.
It so happens that there is a CSS property called animation-direction. This property states whether the animation plays normally or in reverse. Use animation-direction: alternate; to – as the property value indicates – alternate between playing normally and in reverse.
Read more here: MDN: animation-direction
Hope this helps :)