Create a CSS Flipping Animation

Written by David Walsh on February 3, 2014 · 145 Comments

You've all asked for it and now I've added it: Internet Explorer support! Annoyingly enough, the change involves rotate the front and back elements instead of just the container. Skip to this section if you'd like the latered Internet Explorer code. IE10+ is supported; IE9 does not support CSS animations.

CSS Flip

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!

A Note from CSS Animation Expert Ana Tudor

Applying certain properties with certain values (like overflow: hidden) on the card element would disallow it to have 3D transformed children. I believe this is relevant because I got into trouble with overflow: hidden precisely in such cases, where all children of the 3D transformed element were in the same plane, but one or more had been rotated by 180deg.

CSS Flip Toggle

If you'd prefer the element only flip on command via JavaScript, a simple CSS class toggle will do the trick:

.flip-container:hover .flipper, .flip-container.hover .flipper, .flip-container.flip .flipper {
	transform: rotateY(180deg);
}

Adding the flip class to the container element will flip the card using JavaScript -- no user hover required. A JavaScript comment like document.querySelector("#myCard").classList.toggle("flip") will do the flip!

CSS Vertical Flip

Performing a vertical flip is as easy as flipping the axis and adding the transform-origin axis value. The origin of the flip must be updated and the card rotated the other way:

.vertical.flip-container {
	position: relative;
}

	.vertical .back {
		transform: rotateX(180deg);
	}

	.vertical.flip-container .flipper {
		transform-origin: 100% 213.5px; /* half of height */
	}

	.vertical.flip-container:hover .flipper {
		transform: rotateX(-180deg);
	}

You can see that the X access gets used, not the Y.

Internet Explorer Support

Internet Explorer requires significant modifications to the standard flip code because it has not yet implemented all of the modern transform properties. Essentially both the front and back elements need to flipped at the same time:

/* entire container, keeps perspective */
.flip-container {
	perspective: 1000;
	transform-style: preserve-3d;
}
	/*  UPDATED! flip the pane when hovered */
	.flip-container:hover .back {
		transform: rotateY(0deg);
	}
	.flip-container:hover .front {
	    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;
	transition: 0.6s;
	transform-style: preserve-3d;

	position: absolute;
	top: 0;
	left: 0;
}

/*  UPDATED! front pane, placed above back */
.front {
	z-index: 2;
	transform: rotateY(0deg);
}

/* back, initially hidden pane */
.back {
	transform: rotateY(-180deg);
}

/* 
	Some vertical flip updates 
*/
.vertical.flip-container {
	position: relative;
}

	.vertical .back {
		transform: rotateX(180deg);
	}

	.vertical.flip-container:hover .back {
	    transform: rotateX(0deg);
	}

	.vertical.flip-container:hover .front {
	    transform: rotateX(180deg);
	}

With the code above, IE10 will rotate flip the elements as expected!

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?

Comments

  1. Sounds cool and all, but its kind of hard to check out a :hover effect when you’re using a touchscreen. #Justsayin’ ;)

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

  3. A'braham Barakhyahu (@BlessYahu) September 24, 2012

    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.

  4. 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”

  5. -webkit-transform have some bugs with CSS position:absolute. They can’t work together. Keep in mind.

  6. Jean Azzopardi September 26, 2012

    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?

  7. James Burgos September 26, 2012

    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?

  8. Artem Ivanyk September 27, 2012

    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 =)

    • Thanks for your IE10 fix, Artem. It was a help!
      http://codepen.io/KurtWM/pen/xhvHe

    • Leet Ice January 15, 2014

      Thanks for this.. too bad david walsh can’t update the blog to show how this should be done. Took me an extra 30 minutes to figure this out., until i saw your post.

    • Artem, you’re very insightful and effective comment was a life saver. Was specifically having issues with IE and like Leet Ice, found your code and it fixed my situation immediately.

      David Walsh, please consider updating this post with Artem’s code. Your CSS Flip Animation is wonderful and adds a lot (thank you!), but there are still many people using versions of IE that don’t play nice with it and I’m sure Artem’s code could be invaluable to them if it was easier to see.

  9. Awesome David! Any good way to show the backface-visibility during the animation? Every way I’ve tried has had pretty bad performance/flickering.

  10. This is awesome !
    I add this feature (with little adjustements) on http://datagamer.fr/ ;)

  11. 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!

    • yep this is a real pain in the backface-

      one way to resolve, when the anim has finished just set display none on the rear facing element. You have to set display block again before initiating the next animation. Not great but fixes it.

  12. 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?

  13. Anyway we can turn this into a 3D look like this site’s links http://www.pukkelpop.be/nl/bestof ??!!

  14. 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;)

  15. Hey David, awesome work! How can I trigger the transition without hover, but by clicking a button or something?

  16. Galia Ruth December 15, 2012

    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!!!

  17. 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!

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

  19. Thanks for posting. Really useful. Using it now.

  20. 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!

  21. You probably need to prefix perspective, translate, and transform properties to -webkit-.

  22. Hi, Nice work!

    What scripts are included for this to work?

    Best,
    Jon

  23. I been searching for something simple and understandable like this!

    Question: Can I use this on a commercial site?

    thanks

  24. PERFECT!! That was awesome! I was looking for something like this. THANKS!! :)

  25. Nice.
    Knowledge – add prefixes for demo downloads.
    Thank you!

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

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

  28. Hi guys

    Where can I get a working version of this with the vendor preferences because, its just not happening for me on Chrome :(

  29. 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?

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

  31. Brian Scott February 22, 2013

    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?

  32. 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?

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

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

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

  36. Jimmy Soho March 4, 2013

    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?

  37. stiven gordillo March 5, 2013

    no IE

  38. thanx. it works nice.. thanks a lot..

  39. 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!

  40. This isn’t working on internet explorer 9. IE9. Could you please help me out?

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

  42. Don’t work with Samsg s4 browser and Samsg s4 Chrome

  43. Barry Denson April 14, 2013

    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?

  44. Yannick L. April 17, 2013

    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!

  45. Santhosh April 18, 2013

    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.

  46. Hi David, Nice work

    Just IE 7,8,9 – i see its not functional. If it works there – it would be great

  47. 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!!

  48. Argh… please disregard the above comment. Got it working by adding the appropriate vender prefixes to the css.

  49. Rennan May 6, 2013

    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.

  50. 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).

    • Big thanks! Took some browser sniffing to solve my problem. But it is solved!

  51. Semih May 13, 2013

    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 ?

  52. 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?

  53. Celso Santos May 20, 2013

    @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…

  54. Celso Santos May 21, 2013

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

  55. 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…!

  56. I had nothing but trouble in Chrome 25, even after adding vendor prefixes.

    I went with this $6 solution on CodeCanyon, mentioned above, and finally got it to work:

    http://codecanyon.net/item/flipping-cards-3d-with-jquerycss3/3726635

    Highly recommended – tons more features including automatic, timed animations, different flipping directions, etc.

  57. I have same issue with the chrome Version 27.0.1453.110 m. “The back side of the card doesn’t appear when flipped. Anyone else see this?”
    I have used this flip effect from my product page. Please help.

  58. I used your instructions for a personal project, I only added this thing to work with IE10 and touch devices:

    onmspointerdown =”javascript:this.classList.toggle(‘hover’);”

    it seems that ontouchstart doesn’t work with IE ( i know, I shouldn’t worry about MS anymore). I left both, but don’t know if that’s correct.

    • Dear Gabirel

      You’re probably using css reset file.
      I recommend to test without css reset.

  59. Having a strange issue. I am testing a mobile design for my businesses website, and the flip works with hover when I use Safari on my desktop and use the iPhone user agent (to get the proper style sheet).

    However, when using it on the actual iPhone device, it flips on the first tap, but does not flip back on the second tap. The same thing happens in Chrome on my Galaxy Note 2 with taps, HOWEVER #2, if I use the S-Pen (which allows for hovering), the flip works both ways just as it does with :hover on the desktop browsers.

    I am using using the inline “ontouchstart” code just like your example. in fact, all of the CSS i am using is identical to your example, just with renamed classes. Not sure what the problem is, since the code is exactly the same as on your demo page, other than the Width being 100% instead of pixels.

    i also added a javascript alert for touchstart (using jquery ON), to see if the .hover class is being removed properly, and it is. It almost seems like the CSS is not properly updating once the class is removed.

    http://monarchmotel.com/rooms/the-boat-room/?theme=monarch2013

    • I may be running into other issues now. It is a great effect, but i’ll probably skip it for my mobile site for right now (your own demo is having weird issues on my Android phone with Chrome, but not with Safari on my iPhone, weird).

  60. fenix July 4, 2013

    can anybody help me with ie9 and the actuall chrome versions doesnt flip it to the back.
    thy

  61. On transition delay.
    Can anybody help to add the code so that the flipped side remains after having hoovered.
    I tried multiple ways but can’t quite figure what’s going wrong. Thanks.

  62. Hi David
    this looks amazing
    I’m currently working on iPad/iPhone apps that could use this exact feature, but coding is not my strong suit – i’m having a little trouble applying it to my imagery and allowing the interactivity

  63. Hassan July 12, 2013

    Dear David !
    Please tell something about IE ? how it can be work on IE because without IE this work is useless for developers.

  64. David, this is sooo cool. Thanks for sharing this priceless trick!

  65. It took me awhile to get this through to live but I figured you might like to see how I implemented this.
    I even made it degrade to a tool tip for browsers that can’t handle this.
    https://store.enmasse.com/tera

  66. In SASS:

    // Entire container, keeps perspective.
    .flip-container {
      width: 100%;
    
      &:hover .flipper, &.hover .flipper {
        // Front pane, placed above back.
      	.front {
          @include transform(perspective(1000px) rotateY(-179.9deg));
      	}
      	// Back, initially hidden pane.
      	.back {
          @include transform(perspective(1000px) rotateY(0));
      	}
      }
    
      .flipper {
        position: relative;
      }
    
      .front, .back {
      	position: absolute;
      	left: 0;
      	top: 0;
      	width: 100%;
    
      	@include backface-visibility(hidden);
        @include transform(perspective(1000px) rotateY(180deg));
        @include transition-duration(0.6s);
    
        // Front pane, placed above back.
        &.front {
          z-index: 2;
          @include transform(perspective(1000px) rotateY(0));
        }
      }
    }
    
  67. Dragos July 18, 2013

    Any idea how to make this work with 3 flip faces (not 2 like there). I need it like this:
    First face
    Toggle button -> Second face
    Second toggle button -> Third face

  68. Hey there,

    and thank you for the awesome css effect!
    I tried using this in combination with my first steps into flexible layouts, where I have multiple divs of different %width and %height dimensions relative to the browser viewport (think metro ui style tiles). Is there a way this might work without the absolute pixel dimensions in the “.flip-container, .front, .back” classes?

    Thank you in advance!
    Kind regards,
    MWill

  69. It works perfectly! Thanksies!

  70. hello,
    is there a way to make the image a link still using this css?

  71. Thanks, David! This tutorial is flipping easy :)
    I’ve used it (verbatim, for the most part) to add a shuffle button to my photo website.
    Take a look when you can!

    And thank you.

  72. Oops. The website is at http://www.blindinglyordinarythings.com
    You can see the styled css flip on any of the photo pages.

    Thanks!

  73. hi, nice tut and work… but is there an option to have the flip animation but with two different sides, not just one side flipping around ?

    thanks in advance

  74. there are some mistakes in the code but all in all very nice :-)

  75. Kristin August 6, 2013

    Hello! I love this script – thanks so much for posting it!
    I too am trying to make the images flip using a mouse click rather than a hover. I read through the comments and still couldn’t figure out how to do it.
    I tried using javascript and changed my :hover states to .flip-container.hover .front and .flip-container.hover .back, gave my flip-container div this property:

    and added this javascript:

    function hoverthis()
    {
    if (this.className == 'flip-container hover') {this.className='flip-container'}
    else { this.className='flip-container hover'}
    }
    

    But I keep getting errors and it just isn’t working for me. Anyone have any ideas?

  76. Thomasine Stonecypher August 12, 2013

    This is the right website for anybody who wants to learn more about this topic. You understand so much understanding it is hard to not to agree with your viewpoint — not that I really would like to. You definitely put a new spin on a subject that has been written about for ages. Wonderful content!

  77. hi dont know if the source code is corect if i use it it dont work but this css those frome the demo: for tohose who it wont work on crome or safari

    /* simple */
    .flip-container {
    -webkit-perspective: 1000;
    -moz-perspective: 1000;
    perspective: 1000;

    border: 1px solid #ccc;
    }

    .flip-container:hover .flipper, .flip-container.hover .flipper, #flip-toggle.flip .flipper {
    -webkit-transform: rotateY(180deg);
    -moz-transform: rotateY(180deg);
    transform: rotateY(180deg);
    filter: FlipH;
    -ms-filter: “FlipH”;
    }

    .flip-container, .front, .back {
    width: 320px;
    height: 427px;
    }

    .flipper {
    -webkit-transition: 0.6s;
    -webkit-transform-style: preserve-3d;

    -moz-transition: 0.6s;
    -moz-transform-style: preserve-3d;

    transition: 0.6s;
    transform-style: preserve-3d;

    position: relative;
    }

    .front, .back {
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    backface-visibility: hidden;

    position: absolute;
    top: 0;
    left: 0;
    }

    .front {
    background: lightgreen;
    z-index: 2;
    }

    .back {
    background: lightblue;
    -webkit-transform: rotateY(180deg);
    -moz-transform: rotateY(180deg);
    transform: rotateY(180deg);
    }

    .front .name {
    font-size: 2em;
    display: inline-block;
    background: rgba(33, 33, 33, 0.9);
    color: #f8f8f8;
    font-family: Courier;
    padding: 5px 10px;
    border-radius: 5px;
    bottom: 60px;
    left: 25%;
    position: absolute;
    text-shadow: 0.1em 0.1em 0.05em #333;

    -webkit-transform: rotate(-20deg);
    -moz-transform: rotate(-20deg);
    transform: rotate(-20deg);
    }

    .back-logo {
    position: absolute;
    top: 40px;
    left: 90px;
    width: 160px;
    height: 117px;
    background: url(logo.png) 0 0 no-repeat;
    }

    .back-title {
    font-weight: bold;
    color: #00304a;
    position: absolute;
    top: 180px;
    left: 0;
    right: 0;
    text-align: center;
    text-shadow: 0.1em 0.1em 0.05em #acd7e5;
    font-family: Courier;
    font-size: 2em;
    }

    .back p {
    position: absolute;
    bottom: 40px;
    left: 0;
    right: 0;
    text-align: center;
    padding: 0 20px;
    }

    /* vertical */
    .vertical.flip-container {
    position: relative;
    }

    .vertical .back {
    -webkit-transform: rotateX(180deg);
    -moz-transform: rotateX(180deg);
    transform: rotateX(180deg);
    }

    .vertical.flip-container .flipper {
    -webkit-transform-origin: 100% 213.5px;
    -moz-transform-origin: 100% 213.5px;
    transform-origin: 100% 213.5px;
    }

    .vertical.flip-container:hover .flipper {
    -webkit-transform: rotateX(-180deg);
    -moz-transform: rotateX(-180deg);
    transform: rotateX(-180deg);
    }

  78. Subject: IE 10 Problem
    This is really great and I have it working with chrome. I took the code from the demo which Valeri posted and that fixed it in CHROME, but, it would not rotate at all in IE 10. I then applied changes offered by Artem Ivanyk. Those changes caused it to rotate 360 degrees really fast in CHROME. Great if you want a subliminal message in CHROME. In IE 10, it rotates 180 degrees but the back side is in reverse. The print is backwards. If anyone has this working in IE 10 AND CHROME please post the solution. I could use it. Also, the current Demo as of this post is not working with the IE 10 version provided with all Windows 8 computers.

  79. Hi David,
    thanks for the nice article. In Firefox and Safari it looks nice (2D and 3D, respectively). But on my iPad (retina) the vertical flip seems broken.
    Please check out this screenshot: http://www.borislau.de/files/vertical_flip.jpg
    Do you already have a fix for this?
    Best, Boris

  80. janka Mifsud October 2, 2013

    Hi I wanted to see if there is way to get the image to flip every 10 seconds on its own?

  81. and is there a ie 10 fix il be happy if it wil flip as long it dose somthing

  82. hi. very thank you . it was very helpful for me

  83. Is it possible to make the flipped image be a link? So that on a mobile device tapping the image flips it and that image is then tappable as a link?

  84. Great article! Artem Ivanyk, your input came in handy as well when it came time to get my animation working in IE10. Here it is and it works in IE10, Firefox and Chrome. I haven’t tested in Safari. This version animates itself, rather than using hover.

    http://codepen.io/KurtWM/pen/xhvHe

  85. Can you tell me whether this code released for use under a particular license?

  86. I’m trying to create a nice Responsive CSS flipping effect on a banner. I only want the effect to occur on the left side image.

    here is the html:

    <!-- front content -->
    <a href="http://ispeedzone.com" rel="nofollow">
    <img class="fblogo1" border="0" alt="iSpeedzone" </a>
    
    <!-- back content -->
    <a href="http://ispeedzone.com" rel="nofollow">
    <img class="fblogo1" border="0" alt="iSpeedzone" </a>
    
    <img class="fblogo2" border="0" alt="iSpeedzone" 
    

    here is the CSS:

    images{
    
    width: 100%;
    }
    
    img.fblogo1 {
    width: 100%;
    float: left;
    display: inline-block
    }
    
    img.fblogo2 {
    width: 88.5%;
    float: right;
    display: inline-block
    }
    
    /* entire container, keeps perspective */
    .flip-container {
    -webkit-perspective: 1000;
    -moz-perspective: 1000;
    -o-perspective: 1000;
    perspective: 1000;
    }
    
    .flip-container, .front, .back {
    width: 34%;
    height: auto;
    }
    
    .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;
    }
    

    How can I make it work so that the left image will also flip when hovering over the right side image ? (while keeping both images responsive)

  87. I sent you an email earlier today regarding a question for a responsive 2 image flip CSS. Forget about it. I figured it out by myself. Thanks for your help anyways.

  88. Karsten Ohme November 12, 2013

    Awesome!

  89. Good job, David!

    I’m trying to implement it on a page, and when I manage well enough.

    What I want to achieve is that the animations can also be made at the time of loading the page.

    Can you do?

    If so, you would be so kind to tell me how it could be done?

    Thank you!

  90. I can’t get this to work on Firefox. I feel like I added the correct prefixes but I’m new to this. The animation just keeps flipping back and forth. Works on Safari and Chrome. Demo: http://www.wienerwedding.com/wedding_party — I’m already live, please help!

    /* entire container, keeps perspective */
    .flip-container {
    -moz-perspective: 1000;
    perspective: 1000;
    }
    /* flip the pane when hovered */
    .flip-container:hover .flipper, .flip-container.hover .flipper {
    -moz-transform: rotateY(180deg);
    transform: rotateY(180deg);
    }

    .flip-container, .front, .back {
    width: 320px;
    height: 480px;
    margin: 10px 0 10px 0;

    }

    /* flip speed goes here */
    .flipper {
    -moz-transition: 0.6s;
    transition: 0.6s;
    -moz-transform-style: preserve-3d;
    transform-style: preserve-3d;

    position: relative;
    }

    /* hide back of pane during swap */
    .front, .back {
    -moz-backface-visibility: hidden;
    backface-visibility: hidden;

    position: absolute;
    top: 0;
    left: 0;
    -webkit-box-shadow:
    0px 0px 0px 2px rgba(0,0,0,0.6),
    0px 0px 0px 14px #fff,
    0px 0px 0px 18px rgba(0,0,0,0.2),
    6px 6px 8px 17px #555;

    -moz-box-shadow:
    0px 0px 0px 2px rgba(0,0,0,0.6),
    0px 0px 0px 14px #fff,
    0px 0px 0px 18px rgba(0,0,0,0.2),
    6px 6px 8px 17px #555;

    box-shadow:
    0px 0px 0px 2px rgba(0,0,0,0.6),
    0px 0px 0px 14px #fff,
    0px 0px 0px 18px rgba(0,0,0,0.2),
    6px 6px 8px 17px #555;
    }

    /* front pane, placed above back */
    .front {
    z-index: 2;
    }

    /* back, initially hidden pane */
    .back {
    -moz-transform: rotateY(180deg);
    transform: rotateY(180deg);
    background-color: #99CCFF;
    }

    .flip-container {
    -webkit-perspective: 1000;
    -moz-perspective: 1000;
    -o-perspective: 1000;
    perspective: 1000;
    margin: 20px 26px 32px 26px;
    }

    .flip-container, .front, .back {
    width: 240px;
    height: 240px;
    }

    .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;
    }

  91. For the toggle flip, what would the jQuery script look like?

  92. its very good, but i cant see to get the right/bottom border outside of the image prior to hover

  93. Don’t works in IE10 & 11. Any idea how I can only display the backside in IE10 and up?

  94. Nate Zander December 5, 2013

    Hi David-

    I updated OS X to Mavericks last night and noticed my version of your card flip code was broken on my development site in Chrome 31. I spent the past hour trying to figure out what was wrong, so I came back to your original article and realized the demo no longer works on your site either! Have you noticed/heard of any issues with Mavericks (10.9) and Chrome 31?

    The demo works perfectly in Safari.

    Thanks!

    -Nate

  95. Sotiris Iliadis December 17, 2013

    Hello everyone! I am trying to apply a horizontal flip effect but it doesn’t work. I believe that there is a problem with the backface-visibility. Please help! Here is the code:

    .flip-container{
    perspective:1000;
    }
    
    .flipper{
    -webkit-transition:2s;
    -webkit-transition-delay:0,01s;
    transform-style:preserve-3d;
    position:relative;
    }
    
    .flip-container:hover .flipper{
    transform:rotateY(180deg);
    -webkit-transform:rotateY(180deg);
    opacity:0;
    }
    
    .flip-container, .front, .back{
    width:960px;
    }
    
    .front, .back{
    backface-visibility:hidden;
    position:absolute;
    }
    
    .back{
    transform:rotateY(180deg);
    }
    
    .front{
    z-index:2;
    }
    
  96. Great read once again David,

    How would you go about making this responsive?

    Or is there possibly anywhere this has already been made responsive I can see working for help?

    Many thanks

  97. Has anyone adapted this to flip through a calendar which has images above and month below: i.e., each page is a double-side printed, but all files are individual.

  98. Hi David, awesome tutorial. How do I ad some zoom along with flip ? Just like in iOS skype application.

  99. Christopher January 20, 2014

    Hi, I’m new and I have a question. Can your CSS flip technique be used on header or P tags ?

  100. I found it working on Chrome with the code of Valeri look at my sample at http://theweeblytricks.weebly.com/8.html

  101. Great love it

    not working on IE 11 down though!

    FML!

  102. I’ve used this method on my websites some months ago and it was working normally, anyway currently it doesn’t work anymore, even in the david page it is not working as supposed, the back content is not displayed correctly, anyone has a fix for it? I tried managing opacity and z-index but the back content pops up without transition… too ugly…

  103. Jason Purdy January 30, 2014

    This doesn’t seem to be working with Chrome (33.0.1750.46 beta on Ubuntu) where it flips, but the backside doesn’t show up.

  104. Of the few 3d flip effects available on the web, this one is the best and easiest because it doesn’t use jquery. But it doesn’t work on IE, which is a major fallback. I wonder why is Codecanyon’s version working for all IE versions whereas here we are still struggling for the solution.

  105. … There seems to be a solution for all browsers: http://css3playground.com/3d-flip-cards/
    But even if it seems simple, it is very difficult to adapt to David’s script (at least I haven’t managed so far).

  106. Probably everybody knows this (I didn’t): jQuery animations use the computer’s hardware, while CSS3 transitions and animations use the browser’s rendering engine. This is one of the reasons that jQuery animations work on some browsers that don’t support CSS3 transitions.
    So that’s the reason why David’s script doesn’t work in Explorer. Though it seemed to be its best feature, its ability to work only with CSS and no Jquery is its weakest point!

  107. Quick note: This post has been updated to accommodate for Internet Explorer and now works in all browsers!

    • I’m trying out your demo in IE9 and it doesn’t seem to work at all. Did you try IE9?

  108. Vincent Pelletier February 12, 2014

    Thanks for the demo!
    I’m a novice in css (so correct me if i’m wrong) but i think i discovered something in your demo that could be wrong: if the perspective value has no unit, the perspective effect doesn’t apply to Firefox (tested in Firefox 26 & 27). The flip effect does work though.
    If you append an unit to the value (“1000px”), the perspective effect is applied in Firefox.

  109. Vincent Pelletier February 12, 2014

    I hoped that the code in my previous comment would be formatted as, for exemple, in the Sotiris Iliadis comment. It didn’t worked as planned ;-)
    Can someone tell me how to format code in comments?
    Thanks.

  110. Hi David and all,
    I’m a big fan and follower of your stuff and this code rocks!
    I wanted to share with you my implementation of this on a commercial site I have just worked on.
    With some nifty additions one can achieve also a delayed effect on nested flippers, check out the front page here and hover over the larger image grids!
    http://www.outdoorequipped.com/
    Works in all the latest browsers!
    Thanks so much for the clean and understandable coding – really cool – CSS is becoming ever so powerful now :)

  111. I am interested in this effect for my WordPress site that I am working on, but have no knowledge on how or where to put this code for this flip animation. Any and all help would be appreciated – where do I place this code, etc. A “CSS For Dummies” explanation will be helpful (if possible) – again, no knowledge on how to code, just the very basics!! Thx.

  112. This is great! In regards to mobile, the current script works with touch events but how about when there are multiple boxes with this effect.

    Situation:
    I’m doing a list of services with this card effect. Each card will have a title and image of an individual service on the front, and a description on the back. How can I customize the script to flip previous viewed card to the front position while clicking the next card to view the back.

    Thanks.

  113. Hi David,

    Thanks for this wonderful post. Had a question.

    Is there a way to find out in script which side (front or back) is visible at a given time?

    • Of course, you can check the value of the `transform` property. If the value is `rotateY(180deg);`, you’re seeing the back.

  114. Kimberly Randall March 25, 2014

    Hi David,
    This works great for me on desktop; however on iPad if I tap a tile and it flips & then links to another page, when you “go back” to the original page, the tile is still flipped. Is there a way to have the tiles in their original state on “go back”?

  115. Kimberly Randall April 1, 2014

    Hi David,
    I was just following up on my comment above sent on the 25th; is there a fix for that bug?

    ********
    This works great for me on desktop; however on iPad if I tap a tile and it flips & then links to another page, when you “go back” to the original page, the tile is still flipped. Is there a way to have the tiles in their original state on “go back”?
    ********

  116. it is worth mentioning, that this code only works as nice if it is put in style tags directly inside the page. If it is in a css file maybe even with an import, you end up with a weird flick when the page loads. E.g. the content of front and back is loaded first, and then gets initially animated to flick the back to the back

  117. It just wont work for me in Chrome, Safari, Opera – only firefox or IE. Is there something I’m missing – all CSS looks fine to me as updated but can’t get it to work. I think others have had issues but I simply cant see where it is coming from. The front and back content is flipping verically – I’m not sure if this makes a difference?

    Otherwise happy with results! Just want it to work in multiple browsers. CSS here:

    .flip-container {
    	perspective: 1000;
    	transform-style: preserve-3d;
    	position: relative;
    }
    .back {
    		transform: rotateX(180deg);
    }
    .flip-container:hover .back {
    	transform: rotateX(0deg);
    }
    .flip-container:hover .front {
        transform: rotateX(180deg);
    }
    .flip-container, .front, .back {
    	width: 275px;
    	height: 59px;
    }
    .flipper {
    	transition: 0.6s;
    	transform-style: preserve-3d;
    	position: relative;
    }
    .front, .back {
    	backface-visibility: hidden;
    	transition: 0.6s;
    	transform-style: preserve-3d;
    	position: absolute;
    	top: 0;
    	left: 0;
    }
    
    z-index: 2; transform: rotateY(0deg); .back {
    	transform: rotateX(-180deg);
    }
    

    Thanks in advance!

  118. Having failed getting it to work (Vendor Prefixes), viewing, copying and pasting source of the demo then modifying it looks amazing! Thank you.

  119. Hello!

    The code works perfect. But when having multiple instances. On tap flips two a time.

Be Heard

Tip: Wrap your code in <pre> tags or link to a GitHub Gist!

Use Code Editor
Older
JavaScript Debounce Function
Newer
Style External Links with CSS