Create a CSS Flipping Animation
CSS animations are a lot of fun; the beauty of them is that through many simple properties, you can create anything from an elegant fade in to a WTF-Pixar-would-be-proud effect. One CSS effect somewhere in between is the CSS flip effect, whereby there's content on both the front and back of a given container. This tutorial will show you show to create that effect in as simple a manner as possible.
Quick note: this is not the first tutorial about this effect, but I've found the others over-complicated. Many other tutorials add additional styles to code samples which then require the reader to decipher which are needed and which aren't. This tutorial avoids that issue, providing you only the necessary styles; you can pretty up each side of the flip any way you'd like.
The HTML
The HTML structure to accomplish the two-sided effect is as you would expect it to be:
<div class="flip-container" ontouchstart="this.classList.toggle('hover');">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
<!-- back content -->
</div>
</div>
</div>
There are two content panes, "front" and "back", as you would expect, but also two containing elements with very specific roles explained by their CSS. Also note the ontouchstart piece which allows the panes to swap on touch screens. Obviously you should break that code into a separate, unobtrusive JavaScript block if you wish.
The CSS
I'm willing to bet that outside of the usual vendor prefix bloat, you'd be surprised at how little CSS is involved:
/* entire container, keeps perspective */
.flip-container {
perspective: 1000;
}
/* flip the pane when hovered */
.flip-container:hover .flipper, .flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flip-container, .front, .back {
width: 320px;
height: 480px;
}
/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
}
Here's a rough overview of the process:
- The outlying container sets the entire animation area's perspective
- The inner container is the element that actually flips, spinning 180 degrees when the parent container is hovered over. This is also where you control the transition speed. Changing the rotation to -180deg spins the elements in the reverse direction.
- The front and back elements are positioned absolutely so they can "overlay" each other in the same position; their backface-visibility is hidden so the back of the flipped elements don't display during the animation
- The front element has a higher z-index than the back element so the front element may be coded first but it still displays on top
- The back element is rotate 180 degrees, so as to act as the back.
That's really all there is to it!Put this simple structure into place and then style each side as you'd like!
The CSS flip animation has always been a classic, representative example of what's possible with CSS animations, and to a lessor extent, 3D CSS animations. What's better is that there's actually very little CSS involved. This effect would be really neat for HTML5 games, and as a standalone "card" effect, it's perfect. Can you think of anything else you'd use this for?
Sounds cool and all, but its kind of hard to check out a :hover effect when you’re using a touchscreen. #Justsayin’ ;)
I’ve updated the post to work on touchscreen Torkil!
As TORKIL JOHNSEN said already. Needs logic for touch devices. The example page does randomly flip the one or other card.
Besides that, cool stuff.
Can it be found on github?
The post has been updated for touchscreen.
It’s not on GitHub — all of the code to create the effect is in this blog post.
Slick! You can even add a css transition delay so it stays flipped for a little after hovering, which gets close enough to using a click event with javascript.
In Chrome your demos don’t work how you describe. The back is never shown. Rather you just see an exact mirror image of the front.
e.g. When I flip the basic card, I see “tnorf” not “back”
On what platform? Just tested on Mac/Chrome and everything looks correct.
Windows. http://i.imgur.com/sZNPZ.png
I faced the same problem. Worked in Firefox but not in Chrome and Safari. I then went on and added vendor prefixes to all the CSS3 properties such as backface-visibility, transform-style, transition and transform. That sorted it out. Still doesn’t work in Opera and IE9 though.
-webkit-transform have some bugs with CSS position:absolute. They can’t work together. Keep in mind.
Great article, works smoothly on Mac/Chrome.
I think this sentence may be wrong though.. “you can’t pretty up each side of the flip any way you’d like.”, or why can’t you, given that you can target .front and .back?
Ugh, major typo — that should have said “can.”
How might this work in a wordpress scenario where posts are displayed in a thumbnail grid where the featured post image is on one side and the post meta is on the other side? how would the permalink work?
Hey!
Nice article, David. However, there are a couple of things we can do to smooth over cross-browser inconsistencies.
1) There is inconsistency in implementation of perspective property in Firefox 15 and earlier;
2) Also, in Chrome, when you have a complex markup you can encounter issues with positioned children of the indirectly transformed elements(.front and .back in this case). Absolutely positioned elements would flicker and shine through flipped parent during transform, whereas relatively positioned ones would do likewise and even worse — they’ll ignore parent’s backface-visibility and “shine” through it in mirrored way after transform is complete. Workaround is simple — you have to enable hardware acceleration on the element.
So, for the above code you would add:
.flip-container {
/* 1 */
/* For Firefox <= 15 to apply perspective. Without these two lines transformation will be flat.
This fix, however, doesn’t apply if we put overflow property on the element being fixed.
*/
-moz-transform: perspective(1000px);
-moz-transform-style: preserve-3d;
}
.front {
/* 2 */
/*Fix for Chrome, version <= 22*/
-webkit-transform: rotateY(0deg);
/* or this
-webkit-transform: translate3d(0, 0, 0);
any property that triggers hardware acceleration will do the trick
*/
}
But what about IE? What if we want >=IE10 users to have this cool effect (and I think that right now, we, as web-developers, should care more about IE10 than about IE7 or IE8). It comes with Window 8 this October and it won’t support preserve-3d keyword. How do I know? Because I have W8 running on virtual machine; and they actually were not planning to add it for the release of W8 http://msdn.microsoft.com/en-us/library/ie/hh673529(v=vs.85).aspx (see the note under “Transform-style property” heading).
Having that said, we need to modify this code a bit. Instead of flipping one wrapper-element, we’re going to flip both sides of the card simultaneously.
.flip-container {
-webkit-perspective: 1000;
-moz-perspective: 1000;
-o-perspective: 1000;
perspective: 1000;
}
.flip-container, .front, .back {
width: 320px;
height: 480px;
}
.flipper {
-moz-transform: perspective(1000px);
-moz-transform-style: preserve-3d;
position: relative;
}
.front, .back {
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-transition: 0.6s;
-webkit-transform-style: preserve-3d;
-moz-transition: 0.6s;
-moz-transform-style: preserve-3d;
-o-transition: 0.6s;
-o-transform-style: preserve-3d;
-ms-transition: 0.6s;
-ms-transform-style: preserve-3d;
transition: 0.6s;
transform-style: preserve-3d;
position: absolute;
top: 0;
left: 0;
}
.back {
-webkit-transform: rotateY(-180deg);
-moz-transform: rotateY(-180deg);
-o-transform: rotateY(-180deg);
-ms-transform: rotateY(-180deg);
transform: rotateY(-180deg);
}
.flip-container:hover .back, .flip-container.hover .back {
-webkit-transform: rotateY(0deg);
-moz-transform: rotateY(0deg);
-o-transform: rotateY(0deg);
-ms-transform: rotateY(0deg);
transform: rotateY(0deg);
}
.flip-container:hover .front, .flip-container.hover .front {
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
transform: rotateY(180deg);
}
.front {
z-index: 2;
}
And don’t forget to add a fallback for browsers which doesn’t support 3d-transform (which is simple if you’re using Modernizr, you just need to describe alternative behaviour using no-csstransforms3d class).
After all of the above (as of September 2012):
a) FF 15: applies perspective instead of flattening transformation to 2d;
b) Chrome 22: works fine if you took care and applied the fix(or if you don’t have to bother about positioning inside the front card);
c) Safari 5, 6: when it comes to CSS3, there is no browser better;
d) IE7-IE9: no effect, instant show/hide behavior;
e) IE10: flat transforms with no perspective. And we’re hoping that when support for 3d-transforms is added, our code is going to work as intended.
f) Opera 12.02: instant show/hide without the effect, but we’re hoping too =)
Awesome David! Any good way to show the backface-visibility during the animation? Every way I’ve tried has had pretty bad performance/flickering.
This is awesome !
I add this feature (with little adjustements) on http://datagamer.fr/ ;)
Hi David!
The flip effects woks fine, but in safari, when I try to catch any touch/click event on the back pane, it simply does not fire after some flips(see this jsfiddle: http://jsfiddle.net/blurrcat/g6M9d/). The back pane seems to sit on top of the front pane.
This blog(http://daneden.me/2012/04/css-transforms-and-z-index/) points out that z-index gets screwed up when you apply a transform. Is there any way to avoid using z-index?
Thanks!
I tried changing this to flip on the X axis, but I cannot seem to move the origin to the center. It now flips out the top of the container where the back cannot be seen. Any idea what special sauce I need to add to the CSS?
Anyway we can turn this into a 3D look like this site’s links http://www.pukkelpop.be/nl/bestof ??!!
Post coming next week ;)
Hey
Thx David for nice effect, it gives the site another dimension. Keep up the good work.
Also thx for Artem,thx to u it works also for me;)
Hey David, awesome work! How can I trigger the transition without hover, but by clicking a button or something?
Create a class with the :hover selector properties, then add that class to the element that should animate.
Hi, how do you change the codes if you want the card to automatically flip by itself, once, without any mouseover/click?
Please help!!! i have an urgent project due tomorrow!!!
Hi,
I have been trying every imaginable way to make the card slow down when flipping over.
I would like it to stay “flipped” some second more before turning over again.
Transition-delay, for example, does not seem to work…
Does someone here know a way how to do it (make it flip over completely & then stay flipped a bit longer after cursor moves)? Please share :)
Thanks guys!
Hey David, I just made a CSS-animated greeting card where the card comes out of the envelope and everything. I found your examples really helpful. Thanks for posting them! You can see my project at http://markroland.com/project/CSS-greeting-card
Thanks for posting. Really useful. Using it now.
works for me on firefox, but not on chrome and safari, while your demo works on the 3 of them, any ideas?
thanks!
Alright, now that i applied all the fixes it works on chrome and safari but bugs on firefox.
it’s these two that create the difference: with works great on firefox and not on safari chrome, with bugs on firefox
.flip-container:hover .back, .flip-container.hover .back {
.flip-container:hover .front, .flip-container.hover .front {
thanks in advance!
You probably need to prefix perspective, translate, and transform properties to -webkit-.
Hi, Nice work!
What scripts are included for this to work?
Best,
Jon
No JavaScript necessary — just CSS!
I been searching for something simple and understandable like this!
Question: Can I use this on a commercial site?
thanks
Absolutely Elly! Good luck!
PERFECT!! That was awesome! I was looking for something like this. THANKS!! :)
Nice.
Knowledge – add prefixes for demo downloads.
Thank you!
Does anybody have this working in Chrome on Windows?
I’ve managed to get results on:
Mac: Chrome, Firefox, Safari.
PC: Firefox, Safari
IE and Opera are a total bust. I find Window’s Chrome bizarre. I’ve got text displayed correctly, but upon flipping, it’s just rotating the text completely instead of showing the hidden div.
Hey,
Does’nt work for me with the placed css/html. Is there any javascript needed?
I work on Chrome/Windows. The demo cards rotate well.
Hi guys
Where can I get a working version of this with the vendor preferences because, its just not happening for me on Chrome :(
Are you properly vendor-prefixing properties? http://davidwalsh.name/vendor-prefixes
Hi David,
Really cool post. I tried it and works well in Firefox, Chrome and Safari but not on Opera or IE9. Is there a way to get it working? At least on Opera?
Hi,
I am new to CSS. Could u explain me what is happening in the following lines. I cannot u’stand the work of the selectors.
.flip-container:hover .flipper, .flip-container.hover .flipper
Thank you.
Hi,
nice article, clean and simple. One request, when I compare the animation to the live tiles on my windows phone I notice that the windows version actually goes beyond the 180 degrees briefly then eases back into position before facing flush with the user. Is there a way to recreate this with an animations / keyframes declaration?
Thank you, its works amazing. I do only fight with IE10. I was adding the -ms prefixed and it does only rotate the image on first pane on hover. Anyone know how to fix it?
Hi David,
Thank you for this tuto, I have some issues with touch stuffs.
It works as a charm on a laptop, but not on iphone.
Could you take a look at my code if you have 5min to loose :)
Thank you
In fact, the first touch flips the div but the second dont turn it back.
Check this on http://www.l1nkus.com from an iphone.
Hey David, one question… Is that your code on CodeCanyon? lol Well just had to ask since the codes in the source are the same. The one in CodeCanyon was published not too long ago, and I see the one on this page was published last year.
http://codecanyon.net/item/flipping-cards-3d-with-jquerycss3/3726635
I’m trying to get this working with a container that is filling a div 100% height using position:absolute;top:0;left:0;bottom:0;width:300px. Not having much luck.
The code I’m trying:
I expected it to work when I replace “x-effect” with “effect”, but it doesn’t. Anybody knows how to get such a transform working?
no IE
thanx. it works nice.. thanks a lot..
Hi,
I tried to implement this (great tutorial btw). Unfortunately I ran into an issue with background on the div.flipper – Does anybody have a solution to this?
http://jsbin.com/amokax/1/
Great work!
This isn’t working on internet explorer 9. IE9. Could you please help me out?
Thanks David this is awesome, just what I’ve been trying to figure out how to do.
I do have one question though, is there a simple tweak to keep the transition within its containing div?
SoundCloud manage to do it with their widgets: https://soundcloud.com/pages/widgets
Is this a simple modification, if so, could you shed some light on it?
Thanks! :D
Don’t work with Samsg s4 browser and Samsg s4 Chrome
Seems to no longer work in firefox (Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.24) Gecko/20111103 Firefox/3.6.24).
I’ve tested all the examples and none of them seem to work in FF but work in Chrome and IE.
Any idea what has changed in FF to break it?
Works for me in current Firefox and Firefox Nightly.
Hi David,
Thanks, very useful tutorial! But i’ve still some questions. How can I make this flip-effect clickable instead of the hover effect that’s used in the tutorial? I want to create a simple button and when you click on that, it should flip.
Can you give me some more info? Thanks!
Hi David,
I tried this on few browser, Here is the result.
Firefox 21.0 – Works Fine
IE 10 – Flip the text and image, not showing back
Opera 12.15 – No animation
Chrome 26.0 – No animation
Safari 5.1.7 – Works fine
Hope you can find a fix for IE, Opera and Chrome.
Just tried on Chrome 26 on Mac — worked great!
Hi David, Nice work
Just IE 7,8,9 – i see its not functional. If it works there – it would be great
Thanks for the clear tutorial David!
Your demos work fine on chrome 26 for me but I cannot reproduce a working version on any browser.
When I attempt to create my own version, the front and back divs are both viewable all the time, hovering over the div doesn’t initiate any transform. It’s basically a complete fail for me after a few hours of hacking.
Is there any hidden javascript or extra code that isn’t included in your walk-through demo? It would be nice to see a jsfiddle version with all the code necessary.
Thanks again for all your work and selfless contributions to the community!!
Argh… please disregard the above comment. Got it working by adding the appropriate vender prefixes to the css.
Thanks for the clear tutorial David!
I have a question about CSS3 animations. Is there a way to build this animation without using hover or click functions? I´m new using css3 and want to study animations like transitions, to use in games.
Sure Rennan. You would use CSS animations (via keyframes) and then add and remove CSS classes with the animation settings on them.
I rewrote this without using preserve-3d, because Internet Explorer 10 does not support that keyword at this time (Source: http://msdn.microsoft.com/en-us/library/ie/hh673529.aspx). If anyone is interested, my code is available as a GitHub Gist here:
(CSS and SCSS available).
great tutorial. i am working on a card game and i wanted to use this code but didnt figure out how to set flip animation with “onclick” function. can anyone help me ?
This is broken for me in the newest Chrome Canary (29.0.1507.0). The back side of the card doesn’t appear when flipped. Anyone else see this?
@Semih, Yeah, I was also trying to use a click event to set the motion in action, but I jus’t can’t find a way to do it. Tried using an eventListener, but I’m not getting any luck…
@Semih and everyone else who want to have to flip effect activated by clicking, it’s as simple as instead of having ‘.flip-container:hover .flipper’ just rename the class to ‘.flip-container .selected .flipper’ or any other name you see fit and then just have that style applied with click events..
I’m testing some ideas on my dev space and would really like to use this to flip from one image to another. I’m using WordPress and just cannot get this to work – could you help please?! Apologies, I am a complete novice…!