CSS Card Flip isn't showing back face [duplicate] - css

This question already has answers here:
Flip a 3D card with CSS
(2 answers)
Closed 6 years ago.
I've set up a card flip feature where the user can see the back of a card, click and drag it, then click on a hot spot (black bar here) that will then flip the card over.
All of it works except the part where it shows the back of the card. The flip animation happens, it's just blank.
Any help would be greatly appreciated!
Here's where I am...
Here's a fiddle with functionality.
HTML
<div id="flipStage">
<div class="card" id="bsg">
<div class="front" id="bsgFront"></div>
<div class="back" id="bsgBack"></div>
<div class="flipButton"></div>
<div class="handle"></div>
</div>
</div>
CSS
.flipStage {
position: relative;
float: left;
width:100%;
height:100%;
}
.card {
cursor: pointer;
height:175px;
width:125px;
position:absolute;
-webkit-transition: -webkit-transform .5s;
-moz-transition: -moz-transform .5s;
-o-transition: -o-transform .5s;
transition: transform .5s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-perspective: 300px;
-moz-perspective: 300px;
-o-perspective: 300px;
perspective: 300px;
}
.flipped {
-webkit-transform:rotateY(180deg);
-moz-transform:rotateY(180deg);
-o-transform:rotateY(180deg);
transform:rotateY(180deg);
}
.card .front, .card .back {
display: block;
position:absolute;
height:100%;
width:100%;
-webkit-backface-visibility:hidden;
-moz-backface-visibility:hidden;
-o-backface-visibility: hidden;
backface-visibility:hidden;
}
#bsg {
top:150px;
left:150px;
}
#bsgFront {
background-image:url(http://images.penguinmagic.com/images/products/original/8006b.jpg);
background-repeat:no-repeat;
background-size: 100%;
}
#bsgBack {
background-image:url(http://images2.fanpop.com/image/photos/9400000/Tricia-Helfer-BSG-Promotional-Photography-tricia-helfer-9422601-1089-1450.jpg);
background-repeat:no-repeat;
background-size: 100%;
}
.flipButton {
height: 20px;
width: 100%;
position: absolute;
top:0;
right:0;
background-color:black;
}
.handle {
position:absolute;
width: 100%;
height: 100%;
top: 20px;
}

http://jsfiddle.net/gJaCP/3/
You need the initial state of back to be flipped 180.
.back {
-webkit-transform:rotateY(180deg);
-moz-transform:rotateY(180deg);
-o-transform:rotateY(180deg);
transform:rotateY(180deg);
}
I added a bit of text so you can see it flipping. Try a different back image, because the one you are using redirects and I think isn't loading. In my link I used the front again.
I set BG to 50% just so you know it is indeed the back.
http://jsfiddle.net/gJaCP/4/
http://davidwalsh.name/css-flip

Related

Transform and Stacking Order

I am trying to understand what is really happening “3d” world of CSS.
I made a simple example
Particularly the code which bugs me the most is:
.back {
background-color: tomato;
transform: rotateY(180deg);
z-index: 1;
}
The thing which is not clear to me is why when you hover over .inner, its background color (gold) is not visible?? If you remove the transform property from .back or if you set the rotateY to 0deg then the gold background color of the .inner is clearly visible.
Why is the transform property of .back changing the stacking order?
Logically it makes sense that children(.front and .back) should appear in front of their parent(.inner).
Also, I would like to know what really happens when you set transform-style to flat? Does that make parent and all of its children collapse into single “unit” where element with highest stacking order takes priority/visibility?
in your code :
.outer {
display: block;
width: 200px;
height: 200px;
border: 2px solid gold;
perspective: 1000px;
padding: 10px;
margin: 0 auto;
}
.inner {
position: relative;
height: 100%;
width: 100%;
transition: transform 2s linear;
transform-style: preserve-3d;
background-color: gold;
backface-visibility: visible;
transform: rotateY(50deg);
}
.sides {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
color: white;
backface-visibility: hidden;
}
.front {
background-color: blue;
transform: translateZ(20px)
}
.back {
background-color: tomato;
transform: rotateY(180deg) translateZ(10px);
}
.inner:hover {
transform: rotateY(180deg)
}
<div class="outer">
<div class="inner">
<div class="sides front">Front Side</div>
<div class="sides back">Back Side</div>
</div>
</div>
you are using
transform: rotateY(180deg) translateZ(10px);
The transforms are applied right to left, so first it goes to the front 10px. But after that, it rotates 180deg. (around the transform-origin that is constant). That makes the previous 10px go towards the back instead of to the front.
if the order is the inverse
transform: translateZ(10px) rotateY(180deg);
now the rotation is done first, and so the translation is unafected by it and goes to the front.
and No, sorry, z-index is not a substitute for 3-d transforms, if you want to use 3d transforms, translation is the only way to go ....
In your first example, z-index is useless, as can be seen easily
codepen with z-index removed
This works because you are setting
backface-visibility: hidden;
So only the face that is facing front will be visible

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>

CSS Animation: how to trigger the reverse animation?

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.

How to Flip a div and show different sized content on front and back?

I'm trying to create a div "flipcard" element that contains different sized content on the front and back.
The HTML:
<div class="flipcard">
<div class="face front">Front</div>
<div class="face back">Back ... put some long text here ... </div>
</div>
The Javascript just adds and removes a "flipped" class:
$('.flipcard').click(function(e) {
var $card = $(this);
if ($card.hasClass("flipped")) $card.removeClass('flipped');
else $card.addClass('flipped');
});
All the magic happens in the CSS:
.flipcard {
margin: 1em auto;
width: 80%;
/* I don't want to set the height because
we don't know the size of the content */
border: solid 1em white;
border-radius: 0.5em;
font-family: Georgia;
-webkit-perspective: 800;
-webkit-transform-style: preserve-3d;
-webkit-transition: 0.5s;
cursor: pointer;
}
.flipcard:hover {
box-shadow: 0 0 1em black;
}
.flipcard.flipped {
-webkit-transform: rotatey(-180deg);
}
.flipcard .face {
padding: 1em;
text-align: center;
-webkit-backface-visibility: hidden;
}
.flipcard .front {
background: #220000;
color: white;
}
.flipcard .back {
background: #66eeff;
color: black;
-webkit-transform: rotateY(180deg);
}
JSFiddle: http://jsfiddle.net/luken/qdBEV/
As you can see, the content from the front is interfering with the back, and they both stretch the flipcard to the combined height. I'd like the front to show with the proper height of its content and the back to show with the proper height of its content. I've tried making the faces position: absolute and making them go from display: none to display: block on each flip... but nothing works quite right.
Any ideas?
Add proper display:none; and display:block;
Demo: http://jsfiddle.net/qdBEV/3/
CSS:
body {
background: #bbb;
}
.flipcard {
perspective: 800;
-moz-perspective: 800;
-webkit-perspective: 800;
margin: 1em auto;
width: 80%;
border: solid 1em white;
border-radius: 0.5em;
font-family: Georgia;
transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
transition: 0.5s;
-moz-transition: 0.5s;
-webkit-transition: 0.5s;
cursor: pointer;
}
.flipcard:hover {
box-shadow: 0 0 1em black;
}
.flipcard.flipped {
transform: rotatey(-180deg);
-moz-transform: rotatey(-180deg);
-webkit-transform: rotatey(-180deg);
}
.flipcard .face {
padding: 1em;
text-align: center;
backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
.flipcard .front {
background: #220000;
color: white;
display: block; /* added to fix the problem */
}
.flipcard.flipped .front {
display:none; /* added to fix the problem */
}
.flipcard .back {
background: #66eeff;
color: black;
transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
display:none; /* added to fix the problem */
}
.flipcard.flipped .back {
display:block; /* added to fix the problem */
}
I had to implement this problem at work and maybe this post will help others, so here is what I came up with (see jsfiddle). First off, the requirements in my case were a bit tighter than a flipping div with different height faces. Additionally:
There is content below the flip card that has to shift up and down smoothly (e.g. another CSS transiton) while the card flips in order to accommodate for the different heights of the faces.
The content on the faces as well as what is above and below the flip card has to adhere to the responsive design of the page, in other words the card cannot have any fixed CSS dimensions nor absolute positioning.
Support for all major browsers, but only latest versions.
HTML is the same as in the question - one "card" with two "faces":
<div class="flipcard">
<div class="flipcard-front">
<h1>Front</h1>
<p>some shorter content</p>
</div>
<div class="flipcard-back">
<h1>Back</h1>
<p>some long content</p>
...
</div>
</div>
CSS (looks daunting, but actually just a couple of line of LESS):
.flipcard {
position: relative;
height: auto;
min-height: 0px;
/* Flip card styles: WebKit, FF, Opera */
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
-webkit-transition: min-height 1s ease-out 0s, -webkit-transform 1s ease-out 0.5s;
-moz-transition: min-height 1s ease-out 0s, -moz-transform 1s ease-out 0.5s;
-o-transition: min-height 1s ease-out 0s, -o-transform 1s ease-out 0.5s;
/* only height adjustment for IE here */
-ms-transition: min-height 1s ease-out 0s;
}
/* The class that flips the card: WebKit, FF, Opera */
.flipcard.card-flipped {
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
}
.flipcard .flipcard-front,
.flipcard .flipcard-back {
top: 0;
left: 0;
width: 100%;
/* backface: all browsers */
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
/* Flip card styles: IE 10,11 */
-ms-perspective: 800px;
-ms-transform-style: flat;
-ms-transition: -ms-transform 1s ease-out 0.5s;
}
.flipcard .flipcard-front {
position: relative;
display: inline-block;
-webkit-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
-o-transform: rotateY(0deg);
transform: rotateY(0deg);
}
.flipcard .flipcard-back {
position: absolute;
display: none;
-ms-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
transform: rotateY(180deg);
/* webkit bug: https://bugs.webkit.org/show_bug.cgi?id=54371,
You need this fix if you have any input tags on your back face */
-webkit-transform: rotateY(180deg) translateZ(1px);
}
/* The 2 classes that flip the faces instead of the card: IE 10,11 */
.flipcard .flipcard-front.ms-front-flipped {
-ms-transform: rotateY(180deg);
}
.flipcard .flipcard-back.ms-back-flipped {
-ms-transform: rotateY(0deg);
}
Notes: Unfortunately the latest versions of IE still handle CSS rotations differently than all the others in that it expects each face to be flipped individually instead of flipping the card that contains them. Although webKit browsers, FF and Opera seem to "understand" this, I wanted maximal backward compatibility for those browsers and hence all this ugly browser prefix clutter (google for David Walsh's great post on flip cards). Secondly, I wanted older browsers to at least show the right content and so the invisible (back) face had to be display: none while the visible face had to be display: block-inline to avoid collapsed margins with content above and below the card. Thirdly, the shifting of the content following the flip card can be achieved by controlling the cards min-height property while leaving it's height: auto (credit). Running the shift a bit ahead of the rotation makes it really smooth.
Finally, the Javascript:
function flipCard() {
var card = $('.flipcard');
var front = $('.flipcard-front');
var back = $('.flipcard-back');
var tallerHight = Math.max(front.height(), back.height()) + 'px';
// visible/invisible *before* the card is flipped ;D
var visible = front.hasClass('ms-front-flipped') ? back : front;
var invisible = front.hasClass('ms-front-flipped') ? front : back;
var hasTransitioned = false;
var onTransitionEnded = function () {
hasTransitioned = true;
card.css({
'min-height': '0px'
});
visible.css({
display: 'none',
});
// setting focus is important for keyboard users who might otherwise
// interact with the back of the card once it is flipped.
invisible.css({
position: 'relative',
display: 'inline-block',
}).find('button:first-child,a:first-child').focus();
}
// this is bootstrap support, but you can listen to the browser-specific
// events directly as well
card.one($.support.transition.end, onTransitionEnded);
// for browsers that do not support transitions, like IE9
setTimeout(function() {
if (!hasTransitioned) {
onTransitionEnded.apply();
}
}, 2000);
invisible.css({
position: 'absolute',
display: 'inline-block'
});
card.css('min-height', tallerHight);
// the IE way: flip each face of the card
front.toggleClass('ms-front-flipped');
back.toggleClass('ms-back-flipped');
// the webkit/FF way: flip the card
card.toggleClass('card-flipped');
}
This applies the classes for flipping the card/faces. During the transition, the back face has a position: absolute so it is visible while the card is turned. At the same time, the card's height is transitioned. At the end of the transition, the visible face returns to is position: relative and the card's height is derestricted leaving back a responsive page.
Hope this helps - sorry for this lengthy post, it's my first :)

Higher level CSS animation library?

I looked around but can't find any good resources for doing higher level animations (like card flip, cubes, etc). Like a ???:CSS :: jQuery:JS.
I know of transit but I'm looking for something that has more functionality and animations built in.
Have you thought about using Animate.css? Seems pretty good. Another good one seems like CSS3 Animations and for stuff like card-flipping, CSS3 Playground.
An edited version of this one: http://css3.bradshawenterprises.com/flip/:
JSfiddle: http://jsfiddle.net/PnUHr/1/
CSS
#f1_container {
position: relative;
margin: 10px auto;
width: 450px;
height: 281px;
z-index: 1;
}
#f1_container {
-webkit-perspective: 1000;
perspective: 1000;
}
#f1_card {
width: 100%;
height: 100%;
-webkit-transform-style: preserve-3d;
-webkit-transition: all 1.0s linear;
transform-style: preserve-3d;
transition: all 1.0s linear;
}
#f1_container:hover #f1_card {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
box-shadow: -5px 5px 5px #aaa;
}
.face {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
.face.back {
display: block;
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
box-sizing: border-box;
color: white;
text-align: center;
background-color: #aaa;
}
HTML
<div id="f1_container">
<div id="f1_card" class="shadow">
<div class="front face">
<img src="Cirques.jpg"/>
</div>
<div class="back face center">
<img src="Cirques.jpg" style="transform:scaleX(-1), transform:scaleY(-1)"/>
</div>
</div>
</div>
All credits go to the original created (see link). I've just removed the padding that was on the back-facing <div> and added a mirrored background of the front-facing image.
For Mozilla/Gecko browsers you need to add the -moz-* prefixes too. Same for Opera (-o-*) and Internet Explorer (-ms-*`).
Direct image link: http://css3.bradshawenterprises.com/images/Cirques.jpg
Effeckt.css is STILL work in progress but look very promising– a pattern libary of multiple sources.

Resources