Using CSS3 Transitions and Transforms to mimic Mac OS X Stacks behavior

The other day when I wrote Using CSS3 Transitions To Create Rich Effects I was thinking of nice ways to apply this. One of the things that came up was creating the Mac OS X Stacks behavior entirely in CSS!

The working example

In the page CSS3 Transitions – Mac OS X Stacks, which is part of my new CSS3 – Information and samples playground, it displays the stacks in action. Just hover over the bottom image and you will see the effect in action.

Web browser support

This effect runs nice with animation in:

  • Firefox 3.7+ (once CSS Transitions for CSS Transform bug is fixed)
  • Google Chrome 4.0+
  • Safari 4.0+
  • Opera 10.5+

However, and here’s the kicker, I wanted it to work back in Firefox 3.5 and, hold on to something now, Internet Explorer (IE 6+ – now works thanks to great CSS input from Zoltan Hawryluk and Paul Irish)! Since I wanted it to be CSS only, there was no way I could tend to the animation part, but at least get the proper rotation and position when hovering. For Firefox 3.5+ it works automatically since that’s when they implemented support for CSS Transforms.

For Internet Explorer, however, I needed to resort to filters (more specifically, the DXImageTransform.Microsoft.Matrix one), served via a conditional comment. And thankfully, through the help of CSS3 Please! I could generate the degrees value, and that helped me from going insane.

Breaking down the code

The code isn’t particularly advanced, there’s just a fair amount of it, so I won’t show you it in its entirety. However, the basics are:

Container element

All the images are contained within a box with the size of the image initially visible at the button:

.stack-container-bottom {
	position: absolute;
	left: 200px;
	bottom: 0;
	width: 148px;
	height: 130px;
	z-index: 1000;
}

Base setup for images with CSS Transitions

All the images within that box has a CSS Transition applied to them:

.stack-container img {
	position: absolute;
	left: 0px;
	bottom: 0;
	padding-bottom: 5px;
	/* Firefox */
	-moz-transition: -moz-transform 0.3s ease;
	/* WebKit */
	-webkit-transition: -webkit-transform 0.3s ease;
	/* Opera */
	-o-transition: -o-transform 0.3s ease;
	/* Standard */
	transition: all 0.3s ease;
}

This transition sets that it will do a transition for the specified property, the transform one, during 0.3 seconds and it will use easing for the effect.

Hovering the box

When the user hovers the box, it sets a new state for all images via their transform property and will execute the above transition:

.stack-container-bottom:hover img:nth-child(1) {
	/* Firefox */
	-moz-transform: rotate(12deg) translate(-4px, -600px);
	/* WebKit */
	-webkit-transform: rotate(12deg) translate(-4px, -600px);
	/* Opera */
	-o-transform: rotate(12deg) translate(-4px, -600px);
	/* Standard */
	transform: rotate(12deg) translate(-4px, -600px);
}

Each image has a different rotation degree and offset (set through translate), so I used the :nth-child pseudo class to assign each of them their values (using this means I need no classes on the images, and makes it more dynamic). The effect is that the images break out of the surrounding box’s square, but since they are still children element of it, when you hover them, the box is considered to still be hovered too.

However, if you hover the white background between the images, it considered the background being hovered instead, effectively hiding the images – so, the images are now actually aligned to each other but use padding-bottom: 5px to create the visual effect that there is actually a gap there.

And that’s all there is to it! πŸ™‚

Making it work in Internet Explorer

In styles within a conditional comment for Internet Explorer, I use styles applied via a class for each image, then reposition the images through their left and top position and ultimately use the progid:DXImageTransform.Microsoft.Matrix for the rotation. Example:

.stack-container-bottom:hover img.ie-1st {
	left: 115px;
	top: -550px;
	filter:  progid:DXImageTransform.Microsoft.Matrix(
                 M11=0.9781476007338057, M12=-0.20791169081775931, M21=0.20791169081775931, M22=0.9781476007338057, sizingMethod='auto expand'); /* IE6,IE7 */
	-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', 
                 M11=0.9781476007338057, M12=-0.20791169081775931, M21=0.20791169081775931, M22=0.9781476007338057, sizingMethod='auto expand')"; /* IE8 */
	zoom: 1;
}

All code and sample

As mentioned above, in the Transitions – Mac OS X Stacks you can run the example and also see all the code needed to create this effect.

9 Comments

Leave a Reply to Robert Nyman Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.