CSS3 transitions and 3D transforms make it easy to create very nice cube transition (one like you can find in Keynote presentations and few places in Mac OS X).
Demo




Code
In theory:
.front {
transform: translateZ(-100px) rotateY( 0deg) translateZ(100px);
background: gray;
}
.left {
transform: translateZ(-100px) rotateY(-90deg) translateZ(100px);
background: black;
}
.right {
transform: translateZ(-100px) rotateY( 90deg) translateZ(100px);
background: white;
}
.left,.front,.right {
position:absolute; top:0;bottom:0;left:0;right:0;
backface-visibility: hidden;
transition: transform 0.6s ease-in-out, background-color 0.6s ease-in-out;
}
.container {
position:relative; width:100px; height:100px;
perspective: 1000;
}
and then you build:
<div class=container>
<section class=left>
Stuff here
</section>
<section class=right>
Other stuff there
</section>
</div>
and flip classes with script, or use favorite CSS selector trick to do it with “pure” CSS.
Transition of background color simulates light and shade, giving it much more realistic looks.
Some bad news
Currently these CSS modules are Working Drafts, i.e. they’re not a standard yet, it’s still possible that they’ll change in incompatible ways or never become a standard. Some experimental implementations are buggy. Don’t put this code in production, or keep an eye on compatibility problems.
Varying level of browser support and vendor prefixes turn few simple lines into a hyphenated version of coke & mentos.
The cube must have a fixed size in pixels due to design limitation of 3D transforms.
So here we go:
2D fallback
Not every browser supports 3D, and 2D transforms can serve as a decent fallback:
.front {
transform: translateX(0px);
transform: translateZ(-100px) rotateY( 0deg) translateZ(100px);
background: gray;
}
.left {
transform: translateX( 100px) scaleX(0.00000001);
transform: translateZ(-100px) rotateY(-90deg) translateZ(100px);
background: black;
}
.right {
transform: translateX(-100px) scaleX(0.00000001);
transform: translateZ(-100px) rotateY( 90deg) translateZ(100px);
background: white;
}
Scale factor can’t be 0, because it causes division by zero in some matrix computation I’d rather not know about.
You could also add opacity
transition as a fallback for transform-less browsers, but that keeps element clickable, so a proper fallback will need a good’ol script toggling display:none
.
Prefixes
I've dropped experimental -vendor-
prefixed code from this page. I'm waiting for vendors and CSSWG to get their act together.
Different direction
If you swap all X
’s and Y
’s, transition will work from top to bottom. However, transforms exhibit…
Spooky action at distance
Big thanks to Brendan Kenny for explanation
For transitions to work in a sane manner, all transform
properties, everywhere, must have exactly same number and order of transform functions. Otherwise some transforms will be “flattened” to a single matrix, that doesn’t animate well.
If you want to use both horizontal and vertical rotation, the workaround is to add rotateX(0)
before rotateY(…deg)
and rotateY(0)
after rotateX(…deg)
everywhere.
Compatibility
- iOS and Mac Safari — Nice and smooth.
- Firefox 4, Fennec beta for Android — Works ok, but uses 2D fallback.
- Opera Mobile 11, Opera 11 for Desktop — Works ok, but uses 2D fallback.
- Chrome 12 — Works ok, but rendering lacks anti-aliasing and images flicker.
- Android “Honeycomb” Browser — Rendering lacks anti-aliasing, images flicker and back surface remains visible.
- Android 2.1 Browser — Perspective is flattened and images are not rendered at all.
- Kindle 3.1 experimental browser — Works! However, perspective is flattened and animation on e-ink screen is pointless.
- IE9 — Nope. IE10 might support it, but I haven't tested it.