Experimenting with CSS3 Transitions – Flip

Published on August 10th, 2011 Link

In the process of experimenting with integrating SoundCloud into my "takeoff" experimental social network data exploration I decided I'd like to emulate the iOS iPod app "Album Flip" effect, used to create a visual link between the names of a song on an album and the cover artwork.

Javascript libraries such as my personal favourite, jQuery have brought the web a long way in terms of user interface interactivity, dynamic content and animation while avoiding external plugins such as Flash and Silverlight (which I believe still have their place, albeit very limited). More recently the spotlight has been on shifting the processing of animations from frame level mathematics in scripted languages to stylistic directions executed in the most efficient method possible by the browser. Enter CSS 3.

CSS 3 support has improved over the last few years, however not all features are supported by all browsers. Front end web developers are still recommended to use browser specific extensions alongside the recommended CSS 2 specs and working draft selectors and properties.

This demo may not work in all browsers. Only Webkit and Moz prefixed properties have been included. Click on the box below.


To create this effect, several layers of divs must be used. There are two faces on the virtual album cover – the artwork and the back. These two faces are created by divs, and must both be contained inside another div element.

This encapsulating DIV allows the two faces to be animated as a single piece. One face starts rotated 180º along the axis which the entire cover will be rotated.

The CSS 3 perspective property is applied to the container div. This sets up the 3D view of the child elements and defines how deep the animation will distort them in 3D space. transform-style: preserve-3d is applied to the "face" divs which causes any content inside them to skew along with their parent. The "face" divs also have the backface-visibility: hidden property applied.

This property is important here as it allows the two faces to be on opposite sides of the virtual album cover without seeing through to one in reverse. Usually this would result in the uppermost element in the z-stack being the only to display, however some browsers may show rendering artefacts

The most difficult part of this setup is conceptualising how two rotations from different directions could overlap and look to be one object.

To allow the leading edge of the cover to line up with its container, so that the cover appears to be pivoting along the side, the transform-origin is also animated, beginning on the left and ending on the right when going from front to back.

The animation is triggered in this case by a simple class-switch in a function called by Java Script. The entirety of the animation is thereafter only defined in CSS.

Any HTML content can be displayed in the face DIVs as usual, and will be skewed accurately by the browser's rendering engine. In fact, inner content can also be animated, allowing for endless possibilities of layered effects

The CSS for this demo appears bellow

                #albumFlipExample {
		#albumFlipExample .album3D {
			-webkit-perspective: 300;
                        margin:0 auto;
			background-color: #ddd;
			box-shadow:inset 2px 2px 10px #000000; 
			-moz-box-shadow:inset 2px 2px 10px #000000;
			-webkit-box-shadow:inset 2px 2px 10px #000000;

		#albumFlipExample .album3D .jewel{
			-webkit-transform-style: preserve-3d;

		#albumFlipExample .album3D .jewel .face{
			-webkit-backface-visibility: hidden;
			-webkit-transition: -webkit-transform 1s;
			-moz-transition: -moz-transform 1s;

		#albumFlipExample .album3D .jewel .info {
			-webkit-transform-origin: right center;
		#albumFlipExample .album3D .jewel .artwork {
			-webkit-transform-origin: left center;

		#albumFlipExample .album3D .jewel .info{   
			-webkit-transform: translateX(0) rotateY( 0deg );
			-moz-transform: translateX(0) rotateY(0deg);

                #albumFlipExample .album3D .jewel .artwork{
			-webkit-transform: translateX(100%) rotateY( 180deg );
			-moz-transform: translateX(100%) rotateY( 180deg );

		#albumFlipExample.flipped .album3D .jewel .info {
			-webkit-transform: translateX(-100%) rotateY( -180deg );
			-moz-transform: translateX(-100%) rotateY( -180deg );

		#albumFlipExample.flipped .album3D .jewel .artwork {
			-webkit-transform: translateX(0%) rotateY( 0deg );
			-moz-transform:  translateX(0%) rotateY( 0deg );