CSS Animation: how to trigger the reverse animation? - css

I'm trying to create a simple reusable CSS class so I can have this animation everywhere.
Everything works fine except that I can't find any example/documentation on how to trigger the reverse animation.
Here is my HTML:
<div class="cards">
<div class="card">
<div class="frontpage">
<img src="http://lorempixel.com/400/200/"/>
</div>
<div class="rearpage">
<img src="http://lorempixel.com/g/400/200/"/>
</div>
</div>
<div class="card">
<div class="frontpage">
<img src="http://lorempixel.com/400/200/"/>
</div>
<div class="rearpage">
<img src="http://lorempixel.com/g/400/200/"/>
</div>
</div>
</div>
My animation is a "card-flip"-like animation using a simple toggleClass in Javascript to trigger the animation:
$('.card').click(function(){
$(this).toggleClass('opened');
});
And here is my CSS:
.cards {
width: 800px;
margin: auto;
}
.card {
width: 200px;
height: 100px;
position: relative;
display: inline-block;
margin: 10px;
}
.card .frontpage, .card .rearpage {
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
}
.card .rearpage {
width: 0%;
}
.card .frontpage img, .card .rearpage img {
width: 100%;
height: 100%;
}
/***** ANIMATIONS *****/
/* ANIMATION 1 */
.card .frontpage {
-webkit-animation-duration: 1s;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: ease-in;
-webkit-animation-fill-mode: forwards;
}
.card.opened .frontpage {
-webkit-animation-name: frontToRear;
}
#-webkit-keyframes frontToRear {
0% { width: 100%; }
50% { width: 0%; margin-left: 50%; }
100% { width: 0%; }
}
/* ANIMATION 2 */
.card .rearpage {
-webkit-animation-duration: 1s;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: ease-in;
-webkit-animation-fill-mode: forwards;
}
.card.opened .rearpage {
-webkit-animation-name: rearToFront;
}
#-webkit-keyframes rearToFront {
0% { width: 0%; }
50% { width: 0%; margin-left: 50%; }
100% { width: 100%; }
}
What is the smart way of doing this? I wish I could just put some trigger on my .rearcard to trigger the reversed animation but I can't find any way of doing this.
I know I could just write 2 other "reversed" animations and apply them but it seems so dumb that I can't try to do better.
I set up a jsfiddle to help you analyze and test out: http://jsfiddle.net/9yp3U/

Your approach with margin and width to fake a rotation is very interesting, but you can do this much more simply with rotateY
.cards {
width: 800px;
margin:auto;
-webkit-perspective:1000;
}
.card {
width: 200px;
height: 100px;
position: relative;
display: inline-block;
margin: 10px;
-webkit-transition: 1s ease-in;
-webkit-transform-style: preserve-3d;
-webkit-transform:translateZ(1px);
}
.card .frontpage, .card .rearpage, img {
width: 100%;
height: 100%;
position: absolute;
top:0;
left:0;
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
}
.card img {
width: 100%;
height: 100%;
}
.card .rearpage,
.card.opened {
-webkit-transform:rotateY(180deg);
}
Demo
As for the question you asked, you can play animations backwards by using the animation-direction:backwards property, though with CSS toggling animations is hard. Thus, I'd recommend you use a transition instead since it's only a change between two states.
And FYI just in case, CSS selector don't always have to be in the parent child format. In your case applying just .child will do the same. The parent child selector is only necessary when needing to a higher selector specificity than existing properties.
Oh, and also FYI, jQuery isn't needed for this. I included an (untested) javascript equivalent if you want. If this is the only place where you're using jQuery on your page I'd recommend not using it because loading the whole jQuery library takes some time and data.

Related

Different transition-delay - animation finished vs not finished (css only)

SOLUTION:
The solution I found is using two divs on top of each other(to make the function clearer I made one of the divs red), while it has to animate two divs for the effect, it should still be cleaner and faster than using javascript:
.outerDiv {
width: 100%;
height: 50px;
position: relative;
}
.hover1 {
height: 50px;
width: 50px;
background: black;
position: relative;
top: 0px;
transition: width 1s
}
.hover2 {
height: 50px;
width: 50px;
background: red;
position: relative;
top: -50px;
transition: width 1s 1s
}
.outerDiv:hover .hover2 {
width: 100%;
transition: width 0s 0.9s;
}
.outerDiv:hover .hover1 {
width: 100%;
transition: width 1s;
}
<div class="outerDiv">
<div class="hover1"></div>
<div class="hover2"></div>
</div>
This can be achieved by specifying different transition time for the normal state and hover state.
<style>
#hoverDiv {
height: 50px;
width: 50px;
background: black;
transition: width 5s; /*Specify required time.
This affects how long it takes to transition
back to the normal state*/
}
#hoverDiv:hover {
width: 100%;
transition: width 2s; /*This affects how long it takes to transition
into the hover state*/
}
</style>
<div id="hoverDiv"></div>
Also, if you want to add a delay before width decreases back to normal, try
#hoverDiv {
height: 50px;
width: 50px;
background: black;
transition: width 5s;
transition-delay: 5s; /*Waits for 5 seconds and then decreases
back to normal size in 5 seconds*/
}

CSS animation of object-position in Safari 12

Displaying image with object-fit and object-position works in browsers that support them, but in Safari 12, animating the object-position property to create a moving effect doesn't appear to do anything (same with using CSS transitions).
Is this a bug? or am I missing something?
I made a simple box and image to demo: https://codepen.io/Taruckus/pen/zyoGNX
<html>
<head>
</head>
<body>
<div class="wrap"><img src="https://via.placeholder.com/500x2000" alt=""></div>
</body>
</html>
<style>
.wrap {
width: 400px;
height: 400px;
position: relative;
}
.wrap img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
object-position: 50% 0%;
animation: move 5s ease 1 normal forwards;
animation-delay: 0.2s;
}
#keyframes move {
0% {
object-position: 50% 30%;
}
100% {
object-position: 50% 60%;
}
}
</style>
Consider animating transform property. It would be more performant and cross-browser.
Run the snippet below:
.wrap {
width: 400px;
height: 400px;
overflow: hidden;
}
.wrap img {
width: 100%;
transform: translateY(-20%);
animation: move 5s forwards .2s;
}
#keyframes move {
100% {
transform: translateY(-45%);
}
}
<div class="wrap">
<img src="https://via.placeholder.com/500x2000" alt="">
</div>

flexbox animation keyframes on Safari

Why flex keyframes doesn't work in Safari? In other browsers, all works fine.
<div class="a">
<div class="b"></div>
</div>
.a {
height: 200px;
display: flex;
}
.b {
flex:0 1 50%;
border: 20px solid red;
animation: anim-b 1s infinite;
}
#keyframes anim-b {
0% { flex:0 1 0%; }
100% { flex:0 1 100%; }
}
Animations can be picky (buggy) when one mix longhand and shorthand properties.
In this case Safari also has a bug when animating flex-basis, which I just noticed is still not fixed in ver. 11.
https://github.com/DrummerHead/safari-flex-basis-animation-bug
In this case, for the default row direction, you need to use width instead.
Stack snippet
.a {
height: 200px;
display: flex;
}
.b {
flex:0 1 auto;
width: 50%;
border: 20px solid red;
animation: anim-b 1s infinite;
}
#keyframes anim-b {
0% { width: 0%; }
100% { width: 100%; }
}
<div class="a">
<div class="b"></div>
</div>

Show / hide content recursively base on a delay

I am wondering if there is a way in full CSS to reproduce the following animation (the tool-tip box that appears and disappears) and appears again.
I wanted it to be recursive
http://bourbon.io/
You can do this using animations properties (with a custom animation).
Example:
HTML
<div id="container">
<div id="animatediv">
</div>
</div>
CSS
#container {
background-color: yellow;
display: inline-block;
padding: 40px;
}
#animatediv {
width: 100px;
height: 100px;
background-color: red;
position: relative;
animation-name: hideshow;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#keyframes hideshow {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Here's a jsfiddle:
https://jsfiddle.net/fabio1983/j6jj9766/
You can also check this page for more informations:
https://www.w3schools.com/css/css3_animations.asp

CSS flip animation varies in browser

Here is a simple horizontal flip animation - http://jsfiddle.net/vntajmgh/2/
and I see 2 issues:
Open the url in chrome. Hover over the red div. The flip is ok, but the background color for the back div(blue) is not applied.
Open the url in firefox. The flip is like stuck. I can see the blue colored back div sometimes.
I guess it's 'stuck' here because the height is 100vh, which when reduced works fine, but should it not work with the full height too?
.flip-container {
width: 150px;
height: 100vh;
perspective: 800px;
color: #fff;
position: relative;
}
.flipper {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
transition: transform linear 0.6s;
}
.flipper div {
margin: 0;
display: block;
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flipper .front {
background: red;
}
.flipper div:after {
content:"";
display: block;
position: absolute;
top: 0;
left: 0;
background-image: url("http://www.transparenttextures.com/patterns/3px-tile.png");
width: 100%;
height: 100%;
opacity: 0.5;
z-index: 1;
}
.flipper .back {
background: blue;
transform: rotateY(180deg);
}
.flipper:hover {
transform: rotateY(180deg);
}
<div class="flip-container">
<div class="flipper">
<div id="1front" class="front">1-front</div>
<div id="1back" class="back">1-back</div>
</div>
</div>
UPDATE:
Here is the working fiddle - http://jsfiddle.net/gf3g8sz1/1/
Add an overflow hidden to the parent div(flip-container). When we are using 100vh(view port height) with rotate transform property, its actually taking more height than the view port has. so hide it by using overflow hidden.
css
.flip-container {
overflow:hidden;
}
To get the same hover effect in both browser you have to modify the hover CSS.
DEMO
removing:
backface-visibility: hidden;
will make the back color visible
The problem in Chrome is caused by the pseudo element. I have changed the way to get the image blended with red without an pseduo element, and now it works OK.
The problem in FF is caused by the reduced-disappeared size of the element that receives the hover. I have changed the hover so that it is triggered by the container, and now it works also ok.
It is always a good idea to avoid using hover on transformed elements, they usually give some kind of problems
.flip-container {
width: 150px;
height: 100vh;
perspective: 800px;
color: #fff;
position: relative;
}
.flipper {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
transition: transform linear 0.6s;
}
.flipper div {
margin: 0;
display: block;
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flipper .front {
background: red;
background-image: linear-gradient(rgba(255,0,0,0.5),rgba(255,0,0,0.5)), url("http://www.transparenttextures.com/patterns/3px-tile.png");
}
.flipper .back {
background: blue;
transform: rotateY(180deg);
}
.flip-container:hover .flipper {
transform: rotateY(180deg);
}
<div class="flip-container">
<div class="flipper">
<div id="1front" class="front">1-front</div>
<div id="1back" class="back">1-back</div>
</div>
</div>

Resources