CSS3 keyframe animation which runs on hover - css

I am trying to make a small keyframe animation.
When the user hovers on a button, I want the background image to move slightly to the right, then back again. So a little "bounce" movement.
In my first example I used a simple hover in CSS that changed the background position from 91% to 93% which results in movement when hovered.
However when I tried to do something similar, to use a keyframe animation called nextarrow, the animation doesn't run.
Here is a JSFiddle showing my working example (button-one) and my non-working example (button-two)
Where have I gone wrong?
http://jsfiddle.net/franhaselden/Lfmegdn5/
.button-two.next:hover{
-webkit-animation: nextarrow 1s infinite;
-moz-animation: nextarrow 1s infinite;
-o-animation: nextarrow 1s infinite;
animation: nextarrow 1s infinite;
}
#keyframes nextarrow {
0% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
100% {
background-position: 91% center;
}
}

Alternative to #jbutler483's answer use Prefix free: Break free from CSS vendor prefix hell!
.button.next{padding:5% 20%;background-image:url(https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-arrow-right-128.png);background-repeat: no-repeat;background-position: 91% center;}
.button-one.next:hover{background-position: 98% center;}
.button-two.next:hover{
animation: nextarrow 1s infinite;
}
#keyframes nextarrow {
0%,100% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
Simple hover version<br /><br />
<input type="submit" value="Next question" class="button button-one green next" />
<br /><br /><br /><br />
Bounce animation version<br /><br />
<input type="submit" value="Next question" class="button button-two green next">
Note: you can combine 0% and 100% since they are the same:
from
#keyframes nextarrow {
0% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
100% {
background-position: 91% center;
}
}
to
#keyframes nextarrow {
0%,100% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
}
or to this
#keyframes nextarrow {
from,to {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
}

You need to prefix your keyframes as well:
DEMO
#-webkit-keyframes nextarrow{ keyframe definition here}
#-moz-keyframes nextarrow{ keyframe definition here}
#-o-keyframes nextarrow{ keyframe definition here}
#keyframes nextarrow{ keyframe definition here}
for example
.button.next{padding:5% 20%;background-image:url(https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-arrow-right-128.png);background-repeat: no-repeat;background-position: 91% center;}
.button-one.next:hover{background-position: 98% center;}
.button-two.next:hover{
-webkit-animation: nextarrow 1s infinite;
-moz-animation: nextarrow 1s infinite;
-o-animation: nextarrow 1s infinite;
animation: nextarrow 1s infinite;
}
#-webkit-keyframes nextarrow {
0% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
100% {
background-position: 91% center;
}
}
#-o-keyframes nextarrow {
0% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
100% {
background-position: 91% center;
}
}
#-moz-keyframes nextarrow {
0% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
100% {
background-position: 91% center;
}
}
#keyframes nextarrow {
0% {
background-position: 91% center;
}
50% {
background-position: 93% center;
}
100% {
background-position: 91% center;
}
}
Simple hover version<br /><br />
<input type="submit" value="Next question" class="button button-one green next" />
<br /><br /><br /><br />
Bounce animation version<br /><br />
<input type="submit" value="Next question" class="button button-two green next">

Related

Creating animated progress bar

I'm trying to create a animated input/progress bar, but just the untracked part must be animated.
#keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
#loading input {
background-size: 100%;
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab); //just random colors as example
animation: gradient 5s ease infinite;
height: 100%;
}
<div id="loading">
<input id="progress" type='range' min="0" max="100" step="0.01" value="0">
</div>
The problem is that I have no idea about how I can make the untracked area animated. Could you please help me fix this?

CSS3 full-width background animation if body height changes

I am trying to get a full-width css3 animation which animates the background. This works fine as long as the height of the body stays at the viewport height. If the content changes and the user needs to scroll, the animation breaks at the bottom:
I already tried to change the css styles of html and body according to some tutorials and ended up with this:
I also tried to set body to 100vh but I think the problem is with the animation itself not scaling properly.
The css for the animation is this:
html {
height: 100%;
}
body {
min-height: 100%;
}
.rememberly-animation {
background: linear-gradient(41deg, #53b5fe, #7abfb4, #5e9793);
-webkit-animation: rememberly-background 30s ease infinite;
-moz-animation: rememberly-background 30s ease infinite;
animation: rememberly-background 30s ease infinite;
}
#-webkit-keyframes rememberly-background {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
#-moz-keyframes rememberly-background {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
#keyframes rememberly-background {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<html>
<body class="rememberly-animation">
</body>
</html>
The class .rememberly-animation is added to the body-tag.
I somehow need the animation to scale the full height if the viewport (the content) is changing and the user needs to scroll down.
Any hints on this?
This is due to background propagation and your background is moving to the html that you have set to be height:100%.
Here is to illustrate the issue:
html {
height:50px;
}
body {
height:100px;
border:2px solid;
margin:0;
}
body {
background: linear-gradient(41deg, #53b5fe, #7abfb4, red);
animation: rememberly-background 30s ease infinite;
}
#keyframes rememberly-background {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
Note how the background is strangely repeating each 50px inside the whole document and not only the body.
To avoid this add a background to the html element:
html {
height:50px;
background:#fff;
}
body {
height:100px;
border:2px solid;
margin:0;
}
body {
background: linear-gradient(41deg, #53b5fe, #7abfb4, red);
animation: rememberly-background 30s ease infinite;
}
#keyframes rememberly-background {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
Your final code can be:
html {
background:#fff;
}
body {
min-height:100vh;
margin:0;
}
body {
background: linear-gradient(41deg, #53b5fe, #7abfb4, #5e9793);
animation: rememberly-background 30s ease infinite;
}
#keyframes rememberly-background {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<div style="height:150vh;">to add scroll</div>
From this you are having another issue explained here: Using percentage values with background-position on a linear gradient
You have to specify a background-size for the animation to work
html {
background:#fff;
}
body {
min-height:100vh;
margin:0;
}
body {
background: linear-gradient(41deg, #53b5fe, #7abfb4, red);
background-size:200% 200%;
animation: rememberly-background 3s ease infinite;
}
#keyframes rememberly-background {
0%,100% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
}

#-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.

Why css animation doesn't work with background size 100%

I'm working with css animation with steps...my problem is:
when step() == (frame length -1) everything is fluid exept that I can't see the last frame
when step() == frame length I can't still see the last frame and animation is messy...
I'm looking for a way to use background 100% (or at least an explanation of why it doesn't work), for I can use it with sprites with differents number of frames and just use step() to adjust to the actual sprite..
Demo:
#sprite1, #sprite2, #sprite3 {
height: 41px;
width: 41px;
background: url('https://img4.hostingpics.net/thumbs/mini_756487pacanim2.png') 0 center;
}
#sprite1 {
animation: sprite 1s steps(3) infinite;
}
#sprite2 {
animation: sprite 1s steps(4) infinite;
}
#sprite3 {
animation: sprite2 1s steps(4) infinite;
}
#keyframes sprite {
100% { background-position: right center; }
}
#keyframes sprite2 {
100% { background-position: 164px center; }
}
Case1: <br>
<div id="sprite1"></div>
Case2:
<div id="sprite2"></div>
What it should be:
<div id="sprite3"></div>
Required. Percentage of the animation duration.
Legal values:
0-100%
from (same as 0%)
to (same as 100%)
Note: You can have many keyframes-selectors in one animation.
sprit image 4 one start on 50% so i gave. check below sample code.
#sprite1, #sprite2, #sprite3 {
height: 41px;
width: 41px;
background: url('https://img4.hostingpics.net/thumbs/mini_756487pacanim2.png') 0 center;
}
#sprite1 {
animation: sprite 1s steps(3) infinite;
}
#sprite2 {
animation: sprite3 1s steps(3) infinite;
}
#sprite3 {
animation: sprite2 1s steps(4) infinite;
}
#keyframes sprite {
60% { background-position: right center; }
}
#keyframes sprite2 {
100% { background-position: 164px center; }
}
#keyframes sprite3 {
50% { background-position: right center; }
}
Case1: <br>
<div id="sprite1"></div>
Case2:
<div id="sprite2"></div>
What it should be:
<div id="sprite3"></div>
You need to change the initial position to be background-position:-33% center; instead of background-position: 0 center;
in this case the four steps will work like this:
step1: background-position: -33% center; which will display img4
step2: background-position: 0% center; which will display img1
step3: background-position: 33% center;which will display img2
step4: background-position: 66% center;which will display img3
#sprite1 {
height: 41px;
width: 41px;
background: url('https://img4.hostingpics.net/thumbs/mini_756487pacanim2.png') -33% center;
}
#sprite1 {
animation: sprite 1s steps(4) infinite;
}
#keyframes sprite {
100% { background-position: right center; }
}
<div id="sprite1"></div>
Try this:
10 = frames/steps;
For Edge you have to calculate the percentage;
#keyframes sprite{
100%{
background-position: calc(100% / (10 - 1) * 10) 0;
background-position: 111.111% 0;/* Edge/IE */
}
}
#container {
width: 50px;
height: 72px;
animation: container 1s linear infinite;
}
#keyframes container {
50% {
width: 72px;
height: 50px;
}
}
#sprite {
width: 100%;
height: 100%;
background-color: red;
background-image: url(http://i.imgur.com/xtk0SCC.png);
background-position: 0% 0;
background-size: calc(100% * 10) 100%;
background-repeat: no-repeat;
animation: sprite 1s steps(10) infinite;
}
#keyframes sprite {
100% {
background-position: calc(100% / (10 - 1) * 10) 0;
background-position: 111.111% 0;/* Edge/IE */
}
}
<div id="container">
<div id="sprite"></div>
</div>

Make a pause during infinite CSS3 animation

I try to make an animation that run every 3 seconds without JavaScript. My animation's duration is 1 second.
I'm only able to wait 3seconds the first occurence then it's a loop of 1s animation.
My code so far: https://jsfiddle.net/belut/aojp8ozn/32/
.face.back {
-webkit-animation: BackRotate 1s linear infinite;
-webkit-animation-delay: 3s;
animation: BackRotate 1s linear infinite;
animation-delay: 3s;
}
.face.front {
-webkit-animation: Rotate 1s linear infinite;
-webkit-animation-delay: 3s;
animation: Rotate 1s linear infinite;
animation-delay: 3s;
}
#-webkit-keyframes Rotate {
from {-webkit-transform:rotateY(0deg);}
to {-webkit-transform:rotateY(360deg);}
}
#-webkit-keyframes BackRotate {
from {-webkit-transform:rotateY(180deg);}
to {-webkit-transform:rotateY(540deg);}
}
#keyframes Rotate {
from {-webkit-transform:rotateY(0deg);}
to {-webkit-transform:rotateY(360deg);}
}
#keyframes BackRotate {
from {-webkit-transform:rotateY(0deg);}
to {-webkit-transform:rotateY(360deg);}
}
I know how to do it with javascript: https://jsfiddle.net/belut/fk3f47jL/1/
I tried this answer without success: Cycling CSS3 animation with a pause period?
Can you help me please?
EDIT
Thanks great answers i'm also able to make this scenario:
wait 2s, run 1s flip, wait 2s, run 1s back_flip, wait 2s.
#f1_container {
position: relative;
margin: 10px auto;
width: 90px;
height: 90px;
z-index: 1;
}
#f1_container {
perspective: 1000;
}
#f1_card {
width: 100%;
height: 100%;
}
img {
width: 90px;
height: 90px;
}
.face {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.face.back {
display: block;
transform: rotateY(180deg);
}
.face.back {
-webkit-animation: BackRotate 5s linear infinite;
}
.face.front {
-webkit-animation: Rotate 5s linear infinite;
}
#-webkit-keyframes Rotate {
0%,40% {-webkit-transform:rotateY(0deg);}
50%,90% {-webkit-transform:rotateY(180deg);}
100% {-webkit-transform:rotateY(360deg);}
}
#-webkit-keyframes BackRotate {
0%,40% {-webkit-transform:rotateY(180deg);}
50%,90% {-webkit-transform:rotateY(360deg);}
100% {-webkit-transform:rotateY(540deg);}
}
It seems like the only way to achieve this is to extend the animation so that it lasts 4s instead of 1s. Then you could delay the animation by animating from 75% to 100% (rather than 0% to 100%).
In doing so, there is essentially an artificial delay in the animation itself. You just have to do the math to figure out how long this delay is in correlation with the total length of the animation itself.
Updated Example
.face.back {
display: block;
transform: rotateY(180deg);
}
.face.back {
-webkit-animation: BackRotate 4s linear infinite;
animation: BackRotate 4s linear infinite;
}
.face.front {
-webkit-animation: Rotate 4s linear infinite;
animation: Rotate 4s linear infinite;
}
#-webkit-keyframes Rotate {
75% {-webkit-transform:rotateY(0deg);}
100% {-webkit-transform:rotateY(360deg);}
}
#-webkit-keyframes BackRotate {
75% {-webkit-transform:rotateY(180deg);}
100% {-webkit-transform:rotateY(540deg);}
}
#keyframes Rotate {
75% {-webkit-transform:rotateY(0deg);}
100% {-webkit-transform:rotateY(360deg);}
}
#keyframes BackRotate {
75% {-webkit-transform:rotateY(180deg);}
100% {-webkit-transform:rotateY(540deg);}
}
I am not sure exactly when it was released, and it's not the most cross-browser approach (does not cover older browsers like I.E. 9) but you could use the animationPlayState style prop. Theres some documentation on this found here if you want to check it out.
animationPlayState=false
webkitAnimationPlayState=false
function pause() {
var animationElement = document.getElementById('animatedItem');
animationElement.style.animationPlayState='paused';
animationElement.style.webkitAnimationPlayState='paused';
}
As you can see this put's the items animation into a "paused"state, to put it back where it left the animation off at, you can set it to the "running" state that this prop accepts.
Here is a quick example I found when browsing Google.
I was able to do this, as #Josh mentioned, by extending the animation. For example, if you want your animation to last 0.5 seconds with a 3 second pause, you make the entire animation 3.5 seconds, and then use percentages to extend it. (0.5 seconds is about 14% of 3.5 seconds.)
In the code below, I created a DIV with transparent gradient that is the same width as the parent, and then animated it from left to right to give a shimmer effect.
.shimmer {
height: 100%;
width: 100%;
position: absolute;
top: 0px;
background-image: -moz-linear-gradient(160deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0) 25%, rgba(255,255,255,0.85) 60%, rgba(255,255,255,0) 100%); /* FF3.6+ */
background-image: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,0)), color-stop(25%,rgba(255,255,255,0)), color-stop(60%,rgba(255,255,255,0.85)), color-stop(100%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
background-image: -webkit-linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* Chrome10+,Safari5.1+ */
background-image: -o-linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* Opera11.10+ */
background-image: -ms-linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* IE10+ */
background-image: linear-gradient(160deg, rgba(255,255,255,0) 0%,rgba(255,255,255,0) 25%,rgba(255,255,255,0.85) 60%,rgba(255,255,255,0) 100%); /* W3C */
background-repeat: repeat-y;
background-size: 30% 100%;
left: -100%;
z-index: 101;
animation-name: shine;
animation-duration: 3.5s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
#keyframes shine {
0% { left: -100%; }
14% { left: 100%; }
100% { left: 100%; }
}
From 14% to 100%, the DIV doesn't move, but the animation continues for additional time, giving the effect of a pause.
You can add an ending state in the animation which will play like a delay. Check the example below, simple animation that runs for 4 sec but the last 3 sec is delayed.
body {
perspective: 500px;
}
/* clear background */
h2 {
text-align: center;
padding: 16px;
margin: 0;
}
/* crops animations that exceeds one line area */
.line {
width: 100%;
height: 4rem;
overflow: hidden;
padding: 0;
margin-bottom: 16px;
}
/* flipping class and key frames*/
.flipX {
animation: 4s anim-flipX ease infinite;
}
#keyframes anim-flipX {
0% {
opacity: 0;
transform: rotateX(9def);
}
20% {
/* animate nothing to pause animation at the end */
opacity: 1;
transform: rotateX(360deg);
}
60% {
/* animate nothing to pause animation at the end */
opacity: 1;
transform: rotateX(360deg);
}
100% {
/* animate nothing to pause animation at the end */
opacity: 1;
transform: rotateX(360deg);
}
}
<body>
<div class='line'>
<h2 class='flipX'>flip vertical</h2>
</div>
</body>

Resources