CSS3-based Zoom Effect

July 29, 2011

Filed under: CSS — Tags: , , , , — Tim @ 10:25 am

The Goal: Create an effect where the content zooms out past the viewer, revealing new content ‘underneath’.

The Rules: No javascript; should work in modern browsers.

The Result: CSS Zoom. Works in the latest versions of Firefox, Chrome, Safari, Opera and IE9. (IE9 doesn’t support the transitions, but that’s OK.)

Caressing HTML

The HTML is pretty straight forward: a container and 4 boxes. (I opted to use HTML5 sections. The full file also has a <nav> element in there to provide internal linking.):

<div id="folio">
	<section id="p1">1</section>
	<section id="p2">2</section>
	<section id="p3">3</section>
	<section id="p4">4</section>
</div>

Stacking the sections is straight forward:

/* ==== Our container ==== */
#folio {
  position: relative;
  ...
}

section {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  opacity: 0;
  ...
}

Non-permanent Viewing

Now all four sections are the same size as the parent div, and are all sitting on top of each other. But only one should be visible at a time, and when the view changes the visible element should zoom past and fade out while the next one appears.

To handle the visibility I opted to set opacity: 0 for all of the section elements. So, when you first load the demo page you just see an empty box.

The visibility (via opacity) of the elements is handled via the :target pseudo-class:

section:target {
  opacity: 1;
}

So anytime a section becomes the target of a link, it pops back into view. To handle the reverse state — any section not the target of a link — I turned naturally to the :not() pseudo-class. (It’s OK if that isn’t natural to you; this is the first time I’ve actually found a use for the selector.)

section:not(:target) {
  opacity: 0;
  ...
}

Moving Pictures

But we don’t want to just change opacity from 0 to 1 and back again with some funky pseudo-classes. The goal was to have the current section fly out past the view to be replaced with the next one. Time to turn to CSS3 Transitions and Transforms.

To set up the timing function, I originally had:

section {
  ...
  transition: all 1s;

This tells the browser to transition all CSS properties from one state to the next over a 1 second period. For example, we could set section {color: blue;} and section:hover {color: red;}. The color change would happen over a 1 second period when the element was hovered on.

To achieve the zoom effect, we can use transform: scale(5);; this will scale, or zoom, our element 5 times its original size. Combine that with our opacity change and we have:

section:not(:target) {
  opacity: 0;
  transform: scale(5);
}

But, with the transition on the section elements the zoom effect occurred in both directions; when an element was no longer a target, it scaled up and faded out, but the target element could be seen scaling down and fading in. While that was cool on its own, it wasn’t the affect I was going for.

The key to unlocking the one-way zoom effect was to separate the timing function. First I moved the transition the section selector to the section:not(:target) selector. Then I added a second timing function for the section:target element and set it to affect opacity only:

section:target {
  opacity: 1;
  transition: opacity 4s;
}

section:not(:target) {
  opacity: 0;
  transition: all 1s;
  transform: scale(5);
}

The result: :target elements instantly scale to normal size, but slowly fades in, while the :not(:target) elements fade out as they scale up. (I set a slower time so it wasn’t jarring to have it instantly snap in before the out-going image was done.)

In the End

Take a look at the source code of the demo to see everything involved. The code above has been cleaned up for presentation — in reality to get all of the transition and transforms to work you’ll need to include the vendor prefixes (-moz-, -webkit-, -o-). You can also see some other CSS3 selectors in use, mainly :nth-of-type(), which was used to set the background images. Yes, I could have used ID selectors, but I didn’t want to. Also in play is background-size: cover to size the background images.

Fisheye Effect via CSS

June 15, 2010

Filed under: CSS — Tags: , , — Tim @ 9:38 pm

On the CSS-d mailing list Gabriele posted a demo titled Pure CSS fisheye menu with icons. It’s a nifty little demo replicating the zooming dock feature you’ll find on Mac and Stardock’s Dock.

I decided to take it one step beyond and utilize CSS 3′s transform properties, resulting in my own Fisheye demo.

I cut out much of Gabriele’s code that handled the zooming and replaced it with Folgers Crystals transition and transform. (Although I kept pretty much everything else she built, including her icons. Thank you Gabriele for the inspiration.)

Specifically, on the navigation anchors we have transition: all .1s ease-in-out. In a nutshell, this says, “All transitions should take .1 seconds to complete and they should do it smoothly.” We also have transform-origin: 50% 0 which moves the center of action to the center top of the anchor box.

It isn’t until we get to the hover/active/focus states that things happen. Here we have transform: scale(1.5), which you’ve no doubt already concluded causes the element to grow by a factor of 1.5. An important thing to note about this, the transform is applied to the anchor element and therefore affect everything inside that anchor, be it a background image, text or foreground image.

Of course it isn’t quite that simple. Because this part of CSS 3 is under development, we need to utilize various vender prefixes. So to see it actually work you’ll need to add -moz-, -webkit- and -o- to the front of all the transform properties. Not surprising there is not support for Internet Explorer, but that’s OK, it doesn’t matter. Anyone using IE won’t know what they are missing. Go see for yourself.

And look for the Easter Egg… .

flickr » A108 Just Fits