reverse keyframe direction of pure css horizontal img slider - css

I am simply trying to reverse the direction my pure css horizontal image slider is sliding. I have tried altering the key frame animation portion with opposite direction, with both - position and toggling left to right, all my attempts do is allow one slide to slide in the correct direction and then just blank white space due to my images float: left;
Here is live jsFiddle. And here is a Jsfiddle of my attempt and how it's rendering (ie. not working. it slides through one image in the correct direction, but not the rest)
Also, my code below.
Mark-Up:
<div class="slider3">
<figure>
<img src="http://img00.deviantart.net/a251/i/2007/347/c/8/drunk_santa_by_yakuks.png">
<img src="http://img00.deviantart.net/a251/i/2007/347/c/8/drunk_santa_by_yakuks.png">
<img src="http://img00.deviantart.net/a251/i/2007/347/c/8/drunk_santa_by_yakuks.png">
<img src="http://img00.deviantart.net/a251/i/2007/347/c/8/drunk_santa_by_yakuks.png">
</figure>
</div>
CSS:
.slider3 {
width: 100%;
max-width: 960px;
overflow: hidden;
}
.slider3 figure img {
width: 25%;
float: left;
background: red;
}
.slider3 figure{
width: 400%;
position: relative;
margin:0;
padding: 0;
animation: 10s slide infinite;
-webkit-animation: 10s slide infinite;
}
#-webkit-keyframes slide {
0% { left:0%; }
16% { left:0%; }
33% { left:-100%; }
49% { left:-100%; }
66% { left:-200%; }
82% { left:-200%; }
100% { left:-300%; }
}

Actually you don't have to do any modifications other than add animation-direction: reverse to the list of rules (or you can set it as a value in the animation shorthand). As you'd have guessed, adding this property-value pair would reverse the flow of your animation.
When you place 4 images on a page (with float: left and 100% width for each), the 1st image is at 0%, the 2nd is at 100%, 3rd at 200% and 4th at 300%. What your current animation does is - start with the left: 0% which means the first image is in view. After sometime the left offset is set as -100% and what this means is that the second image which was at 100% on the page will now get displayed (as 100% - 100% = 0% and so it lands in the viewing area). Similarly the 3rd and 4th also gets shown.
Now to reverse the animation, you need the left offset to start at -300% so that the fourth image is visible first and then it slides towards the right instead of slide towards the left. Note: If you want the first image in the DOM to show up first then change float:left to right for .slider3 figure img.
With fourth image in DOM appearing first: (float: left)
.slider3 {
width: 100%;
max-width: 960px;
overflow: hidden;
}
.slider3 figure img {
width: 25%;
float: left;
background: red;
}
.slider3 figure {
width: 400%;
position: relative;
margin: 0;
padding: 0;
animation: 10s slide infinite reverse backwards;
-webkit-animation: 10s slide infinite reverse backwards;
}
#-webkit-keyframes slide {
0% {
left: 0%;
}
16% {
left: 0%;
}
33% {
left: -100%;
}
49% {
left: -100%;
}
66% {
left: -200%;
}
82% {
left: -200%;
}
100% {
left: -300%;
}
}
#keyframes slide {
0% {
left: 0%;
}
16% {
left: 0%;
}
33% {
left: -100%;
}
49% {
left: -100%;
}
66% {
left: -200%;
}
82% {
left: -200%;
}
100% {
left: -300%;
}
}
<div class="slider3">
<figure>
<img src="http://lorempixel.com/200/200/nature/1">
<img src="http://lorempixel.com/200/200/nature/2">
<img src="http://lorempixel.com/200/200/nature/3">
<img src="http://lorempixel.com/200/200/nature/4">
</figure>
</div>
With first image in DOM appearing first: (float: right)
.slider3 {
width: 100%;
max-width: 960px;
overflow: hidden;
}
.slider3 figure img {
width: 25%;
float: right;
background: red;
}
.slider3 figure {
width: 400%;
position: relative;
margin: 0;
padding: 0;
animation: 10s slide infinite reverse backwards;
-webkit-animation: 10s slide infinite reverse backwards;
}
#-webkit-keyframes slide {
0% {
left: 0%;
}
16% {
left: 0%;
}
33% {
left: -100%;
}
49% {
left: -100%;
}
66% {
left: -200%;
}
82% {
left: -200%;
}
100% {
left: -300%;
}
}
#keyframes slide {
0% {
left: 0%;
}
16% {
left: 0%;
}
33% {
left: -100%;
}
49% {
left: -100%;
}
66% {
left: -200%;
}
82% {
left: -200%;
}
100% {
left: -300%;
}
}
<div class="slider3">
<figure>
<img src="http://lorempixel.com/200/200/nature/1">
<img src="http://lorempixel.com/200/200/nature/2">
<img src="http://lorempixel.com/200/200/nature/3">
<img src="http://lorempixel.com/200/200/nature/4">
</figure>
</div>
You'd notice that I have added a backwards also to the animation short-hand property. This stands for animation-fill-mode and it makes the element hold the state as at its last keyframe until the time the animation starts. If this isn't added there will be a snap at the start where the first image will display before immediately changing to 4th (no slide) with float:left and vice-versa for float: right.
Amr Aly's second answer will work (and there are other possible ways too) but there is absolutely no reason to make it so complex.

Related

CSS Transition : large div disappears completely while animating

I have some problems with a CSS transition effect. I don't understand why, but it isn't working. Here is a demo that isn't working :
https://codyhouse.co/demo/ink-transition-effect/index.html
Here is an article about how this effect was done (before, when it did work) :
https://codyhouse.co/gem/ink-transition-effect
The code I'm working on to debug is this one :
https://codepen.io/1019/pen/YzxzNGX
HTML file :
<body>
CSS ANIMATIONS TEST
<div class='cd-transition-layer'>
<div class="bg-layer"></div>
</div>
</body>
CSS file :
.cd-transition-layer {
position: fixed;
top: 0;
left: 0;
z-index: 30;
height: 100%;
width: 100%;
}
.cd-transition-layer .bg-layer {
position: absolute;
left: 50%;
top: 50%;
z-index: 15;
transform: translateY(-50%) translateX(-2%);
height: 100%;
width: 2500%;
background: url('https://i.imgur.com/9uDdPAP.png') no-repeat 0 0;
background-size: 100% 100%;
animation: cd-sprite 5s steps(24);
animation-fill-mode: forwards
}
.cd-transition-layer.opening .bg-layer {
z-index: 15;
animation: cd-sprite .8s steps(24);
animation-fill-mode: forwards
}
#keyframes cd-sprite {
0% {
transform: translateY(-50%) translateX(-2%)
}
100% {
transform: translateY(-50%) translateX(-98%)
}
}
Can you please help me find what is wrong ?
Thank you !
EDIT : Okay, weird : it seems the div just completely disappears during the animation before reappering. If I keep focus on the div in the inspector, it stays there. Is it because it's too long (2500% width) ?
Moving large divs
It seems that animating a large div over the screen very fast can cause a render/flicker in webkit based browsers.
If i have to guess, it's probably due to performance reasons, where the browser cuts off things thats are not in the viewport. when moving to the next frame, it will not have the pixels ready to be rendered, resulting in a flicker.
It becomes more apparent when you remove the steps(24) from the animation.
The div will slide over the screen, and at some point just stop being visible.
Using background-position instead
When animating, instead of moving a div over the screen, we can also opt to move only the background instead.
background: url("https://i.imgur.com/9uDdPAP.png") no-repeat;
background-size: 2500% 100%; /* Size is needed to stretch 1 frame to fit the div */
background-position: 0% 0%; /* we can start from frame 0 */
animation: cd-sprite 1s steps(24);
/* the animation is the same, we only move the background instead. (in 24 steps) */
#keyframes cd-sprite {
0% {
background-position: 0% 0%;
}
100% {
background-position: 100% 0%;
}
}
* {
box-sizing: border-box;
}
.cd-transition-layer {
position: fixed;
top: 0;
left: 0;
z-index: 30;
height: 100%;
width: 100%;
}
.cd-transition-layer .bg-layer {
position: absolute;
left: 50%;
top: 50%;
z-index: 15;
height: 100%;
width: 100%;
background: url("https://i.imgur.com/9uDdPAP.png") no-repeat;
background-size: 2500% 100%;
background-position: 4.16% 0%;
transform: translateY(-50%) translateX(-50%);
animation: cd-sprite 1s steps(24) infinite;
animation-direction: alternate;
animation-delay: 1s;
animation-fill-mode: forwards;
border: 36px solid red;
}
#keyframes cd-sprite {
0% {
background-position: 0% 0%;
}
100% {
background-position: 100% 0%;
}
}
<body>
<div class='cd-transition-layer'>
<div class="bg-layer"></div>
</div>
</body>

I have one SVG that is rotate around a svg but is not fixed

<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
transform: translate(45px,-75px);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
The problem is what when i zoon out/in or resize the brower .pic2
is moving not stay fixed on his original point
Your idea is right yet both SVG images will adjust to the proportion of the available space (do you have only viewBox defined in them, removing the height and width attributes?). So the second image (pic2) will always "bounce" when resizing (but how many web users really do that?).
Maybe define styles for both SVGs in their DIV parent (or "container" element if you wish) by using vw and vh units - instead of pixels, possibly percentages as well - and this will at least give you more predictable result:
<style>
body {
border: 0;
margin: 0;
}
.pic1 {
position: absolute;
width: 100%;
border: 0;
margin: 0;
}
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
z-index: -1;
transform: translate(2.5vw,88vh);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
</style>
<body>
<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
</body>

Svg anomation rotate is not fixed [duplicate]

<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
transform: translate(45px,-75px);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
The problem is what when i zoon out/in or resize the brower .pic2
is moving not stay fixed on his original point
Your idea is right yet both SVG images will adjust to the proportion of the available space (do you have only viewBox defined in them, removing the height and width attributes?). So the second image (pic2) will always "bounce" when resizing (but how many web users really do that?).
Maybe define styles for both SVGs in their DIV parent (or "container" element if you wish) by using vw and vh units - instead of pixels, possibly percentages as well - and this will at least give you more predictable result:
<style>
body {
border: 0;
margin: 0;
}
.pic1 {
position: absolute;
width: 100%;
border: 0;
margin: 0;
}
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
z-index: -1;
transform: translate(2.5vw,88vh);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
</style>
<body>
<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
</body>

CSS Animation - drawing line from left to right on mouseenter, then disappearing left to right on mouseleave

I'm trying to animate a line that underlines from left to right on 'mouseenter' and then to disappear from left to right on 'mouseleave' instead of the current behaviour where it disappears right to left.
Example of what I'm trying to achieve (but with animations not transitions):
https://jsfiddle.net/1gyksyoa/
I have tried to reverse the 'draw' animation but this doesn't achieve what I'm trying to accomplish.
#keyframes draw-reverse {
100% {
width: 0;
background-color: red;
}
0% {
width: 47px;
background-color: red;
}
}
I have put together this to give a better understanding of the problem;
https://jsfiddle.net/Lq560be9/
Currently, I have the line animating from left to right as desired on 'mouseenter', but on 'mouseleave' it disappears from right to left, whereas I am trying to get the line to also disappear from left to right.
But the problem isn't animation's ability it's the properties that you're animating. Instead of animating the width of an object you should animate its "X" position using translate. (this is much more performant too)
Simply put you need to MOVE the bar from left to center to right instead of trying to scale it.
(there's lots of code here to show the different states the only one you really need to follow is .ex4)
document.querySelector('#animate').addEventListener('mouseenter', function(){
this.classList.toggle('over');
})
document.querySelector('#animate').addEventListener('mouseleave',function(){
this.classList.toggle('out');
})
.example {
margin: 30px auto;
padding: 10px;
background: #dadada;
max-width: 50%;
position: relative;
}
.example:after {
content:'';
position: absolute;
width: 50%;
height: 5px;
background-color: #333;
left:0;
bottom:0;
}
.ex1:after {
transform: translateX(-100%);
}
.ex3:after {
transform: translateX(200%);
}
.ex4 {
overflow: hidden;
}
.ex4:after {
transform: translateX(-100%);
}
.ex4.over:after {
animation: animate-in 1s ease-in-out 1 normal forwards;
}
.ex4.out:after {
animation: animate-out 1s ease-in-out 1 normal forwards;
}
#keyframes animate-in {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(0);
}
}
#keyframes animate-out {
0% {
transform: translateX(0);
}
100% {
transform: translateX(200%);
}
}
<div class="example ex1">Object State 1</div>
<div class="example ex2">Object State 2</div>
<div class="example ex3">Object State 3</div>
<div id="animate" class="example ex4">Full example (hover)</div>
As a follow on from above, an alternative solution without using the translate property.
The new animation for mouseleave is;
#keyframes draw-reverse {
0% {
width: 47px;
}
25% {
width: calc(100% - 16px);
}
26% {
width: auto;
right: 8px;
left: 8px;
}
100% {
width: auto;
right: 8px;
left: calc(100% - 8px);
}
}
Full solution can be seen here - https://jsfiddle.net/1wq25tg7/

CSS Keyframes Slide not working on Background image

Using the second answer found here. I combined my images into a sprite and then updated my CSS to reflect the keyframes element like in the example provided. The sprite image (castle) shows up but the slide effect does not take place? What am I missing?
Sample URL, center element on home page: http://216.157.26.175/cookiedouglas/
Here is my CSS:
.agentpress-pro-cookie .home-featured .widget {
/* background-color: rgba(255, 255, 255, 0.8); */
background: url("http://216.157.26.175/cookiedouglas/wp-content/uploads/sites/58/2015/05/fort-myers-homes-for-sale.jpg");
opacity: 0.95;
content: '';
/* position: absolute;
width: 400%;
height: 100%; */
z-index: -1;
/* background: url(http://placekitten.com/500/500/); Image is 500px by 500px, but only 200px by 50px is showing. */
animation: slide 3s infinite;
}
#keyframes slide {
20% {
left: 0;
}
40%, 60% {
left: -50%;
}
80%, 100% {
left: -100%;
}
}
Use browser (vendor) specific prefixes.
Browser prefixes are used to add new features that may not be part of a formal specification and to implement features in a specification that hasn’t been finalized.
CSS3 animation is one of those features. It has partial support across different browsers. Browser support for CSS3 animations can be checked here.
As evident from the above link, to make the animation work on browsers other than IE and Firefox, you meed the -webkit- prefix.
Also, CSS left propery works only with absolutely positioned elements.
So you should try something like this (read added comments in snippet for explanation):
/*visible portion of the larger 5120x680 pixel image*/
.widget {
width: 1024px;
height: 680px;
position: relative;
overflow: hidden;
border: 1px solid black;
}
.widget:before {
content: '';
position: absolute;
/*needed for CSS left property to work*/
width: 5120px;
height: 680px;
z-index: -1;
/*ExampleImageSprite.jpg is a 5120x680 pixel image which is a combination of 5 individual 1024x680 pixel images*/
background: url("https://dl.dropboxusercontent.com/u/192824325/00_sandbox/30150865/ExampleImageSprite.jpg");
-webkit-animation: slide 10s infinite;
animation: slide 10s infinite;
}
#-webkit-keyframes slide {
0% {
left: 0px;
}
20% {
left: -1024px;
}
40% {
left: -2048px;
}
60% {
left: -3072px;
}
80% {
left: -4096px;
}
100% {
left: -5120px;
}
}
#keyframes slide {
0% {
left: 0px;
}
20% {
left: -1024px;
}
40% {
left: -2048px;
}
60% {
left: -3072px;
}
80% {
left: -4096px;
}
100% {
left: -5120px;
}
}
<div class=widget></div>

Resources