Grow your CSS skills. Land your dream job.

Rotating Feature Boxes

Published by Chris Coyier

This is what we're going to build:

The full effect of it (with transition animations) will work in newish WebKit and Opera browsers and Firefox 4 (in real beta as of today). Any other browser will rotate the blocks without transition animation.

View Demo   Download Files

The Interesting Part

All the animation is CSS3 transitions. JavaScript only watches for the clicks and applies and removes classes as needed. Why not use JavaScript for the animations as well and get wider browser support? CSS3 is far better suited for this. The animations are better (hardware accelerated). It doesn't slow down other JavaScript. It is also easier to write keeping the animations in CSS. With JavaScript we aren't able to animate to classes* easily.

As more time passes, more and more animations will be relegated to CSS and away from JavaScript libraries.

HTML

We'll give ourselves a semantic wrapper, which also provides the relative positioning context for all the blocks. The blocks are positioned with absolute positioning and ultimately animated by changing their top/left values, so that relative context is important. Each block has a div wrapper with a unique ID, as well as a class name indicating its current state. There are three self-explanatory state classes, starting with the obvious active which is the block currently in the fully viewable left-most state.

Each block has a subtitle which is viewable only when non-active and another div wrapper containing everything to be displayed when the block is active. The subtitle idea gives the opportunity to provide some kind of short teaser and entice clicks.

<div id="rotator">

	<div id="block-1" class="active">
		<h2>Subtitle #1</h1>
		<div>
			<h1>Seven Space Frogs Descend On Canada's Largest City</h1>
			<img src="spacefrog.jpg" alt="space frog">
			<p>Commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
		</div>
	</div>
	
	<div id="block-2" class="non-active-top">
		<h2>Subtitle #2</h2>
		<div>
			<h1>The Power of the Voodoo. Who do? You do.</h1>
			<img src="goblins.jpg" alt="goblins">
			<p>Ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
		</div>			
	</div>
	
	<div id="block-3" class="non-active-bottom">
		<h2>Subtitle #3</h2>
		<div>
			<h1>You May Find Yourself Living in a Shotgun Shack</h1>
			<p>Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus</p>
		</div>			
	</div>

</div>

CSS

Set up the wrapper and context:

#rotator { width: 920px; height: 280px; position: relative; background: white; padding: 20px; }

Unique styling to any of the blocks can be done through ID:

#block-1 { background: #d5fcff; }
#block-2 { background: #e1ffd5; }
#block-3 { background: #ffffd8; }

Each block shares some properties, in that the overflow is hidden, they are positioned absolutely, and will the animated at the same speed:

#rotator > div { 
	position: absolute; 
	overflow: hidden;
	-webkit-transition: all 0.5s ease;
	-moz-transition: all 0.5s ease;
	-o-transition: all 0.5s ease;
}

The three states of the boxes determine their size and position:

#rotator .active { top: 20px; left: 20px; width: 580px; height: 280px; }
#rotator .non-active-top { top: 20px; left: 620px; height: 130px; width: 320px; }
#rotator .non-active-bottom { top: 170px; left: 620px; height: 130px; width: 320px; }

The subtitle (h2) ends up being the exact size of the box by setting its line-height equal to the height of the box. This pushes everything else out of the way and hidden, since the overflow is hidden. Then when the box is in it's active state, we hide the subtitle and everything else is revealed naturally.

#rotator h2 {
	text-align: center; 
	line-height: 130px;
}
#rotator .active h2 {
	display: none;
}

jQuery

We make a rotate function which applies the proper classes to the proper blocks depending on what the current value is. There is probably a cleaner way to do this which scales better...

function rotate() {
				
	if (current == 1) {
		$("#block-1").removeClass().addClass("active");
		$("#block-2").removeClass().addClass("non-active-top");
		$("#block-3").removeClass().addClass("non-active-bottom");
	} else if (current == 2) {
		$("#block-1").removeClass().addClass("non-active-bottom");
		$("#block-2").removeClass().addClass("active");
		$("#block-3").removeClass().addClass("non-active-top");
	} else {
		$("#block-1").removeClass().addClass("non-active-top");
		$("#block-2").removeClass().addClass("non-active-bottom");
		$("#block-3").removeClass().addClass("active");
	}

}

Then we attach a click handler to each of the blocks. When they are clicked, we figure out which one it is through it's ID, set the current value to that, and call the rotate function.

$("#rotator div").click(function() {
	current = this.id.substr(6);			
	rotate();
});

Credit to Andrea Canton for the idea on checking which block was clicked, which enables the blocks to rotate in either direction which is more satisfying.

All Together Now

So you click a block, that block's class' are adjusted. The new classes have different size and position values. Because the block has transition CSS applied, those new sizes and postion values are animated to. Easy cheezy.

View Demo   Download Files


*jQuery UI has the ability to animate to classes by extending jQuery's addClass. It falls short in this scenario though, as we need to remove the previous class first (moving it back to a default location) before adding the new one, which makes the animations jumpy and wrong.

Comments

  1. Awesome overview of a simple technique using CSS animations. :)

    I can’t wait until FF4 becomes more standard. Mozilla based browsers are really missing out on this stuff.

    Thanks Chris!

  2. Dance! Dance Magic Dance!

  3. Good one chris…:)

    Keep going…:)

  4. Awesome!

    Can we name this trick the “do-si-do”?

  5. Thanks! You know how you start to learn something and get lost? And then you get that one tutorial where you think “oh i get it now!” Well, tthis was that tutorial for me. Thanks Chris.

  6. João
    Permalink to comment#

    I couldn’t stop clicking!

  7. Permalink to comment#

    Woosh ! that’s a really cool effect ! Thanks :)

  8. Brian Lang
    Permalink to comment#

    Possible Enhancements:
    1. Add a timer to make them switch automatically. Say every 10 seconds
    2. Add a pause on mouseover feature to stop the timer temporarily. Alternately add pause and play buttons. Or both.
    3. Add a scroll bar for long content so that it’s all viewable.
    4. Add something to indicate to the user that they can click on a subtitle box to get it to show up in the main box.

  9. Permalink to comment#

    Cool effect, but a total usability no-no IMHO.

    • I’m curious as to what would deem this “a total usability no-no”

    • tully
      Permalink to comment#

      I agree. It’s just a gimmick.

    • Permalink to comment#

      I think it’s a pretty cool idea for rotating headlines; featured articles, etc.

      In most browsers (without the animation) it’s a little hard to follow, but adding controls (or a javascript fallback animation) would solve that.

  10. Bjorn C
    Permalink to comment#

    This is awsome, but the coolest thing I think is that substr(); thing you used. I was looking for a way to do that a while ago but coudent figer it out, that is really useful.

  11. Permalink to comment#

    LABRYNTH!!!!!!!!!!!!!! Nice.

  12. Tony
    Permalink to comment#

    Very cool Chris =)

  13. Chris, are you saying that other things equal, CSS > JavaScript for any animation?

  14. Vince
    Permalink to comment#

    First let me say great article :-)

    I still think JavaScript is more suited to animations as it’s a real programming language.

    CSS3 will only ever do simple animations. Nothing like a 3D game, or any game for that matter, that requires logic.

  15. Piers
    Permalink to comment#

    Pretty cool! Doesn’t work with JS disabled but how many people actually disable it? Also, tiny error in your sample html – <h2> subtitle #1 </h1>

  16. Raymond Torres
    Permalink to comment#

    Wouldn’t it make more sense to stick with CSS an use :target instead of click events?
    Here a (simple) example what I mean http://jsfiddle.net/wKw9Y/

    The only problem I see, is that there is now box “open” by default.

  17. Permalink to comment#

    Love it.. After these effects flash will obviously go down..

  18. jkandei
    Permalink to comment#

    For some reason Safari 5.0.3 for Leopard does not display the #1 text and image. Only the empty blue box. Any ideas?

    • Permalink to comment#

      see Piers‘s comment above:

      [...] Also, tiny error in your sample html – subtitle #1

  19. Permalink to comment#

    Great effect.

  20. Permalink to comment#

    I can’t get ANY of the wonderful stuff on this site to work with squarespace :( :(

  21. Permalink to comment#

    Beautiful, i surely will use this one, thanks!

  22. sereal
    Permalink to comment#

    i dont know what to say…

    I love this website Chris…

  23. Vince
    Permalink to comment#

    Professional web developers cater for browsers that have JavaScript turned off. Anyone who doesn’t is an amature.

    • Shane
      Permalink to comment#

      Yes, because most companies don’t take into account the web analytics and target audience.

  24. Really thank you for mentioning me, even if I’ve done a really small enhancement.

    Anyway I hope CSS3 become supported well on every browser soon. It’s really easy to make tricks like this one!

  25. Permalink to comment#

    Flash is becoming a thing of the past!

  26. At first it was just a cool effect… then the Labyrinth quote popped up and it suddenly evolved into “legendary”

    Thanks for sharing.

  27. This is just incredible. Shame it does not function as intended in Firefox but at least it does still work. Tried it in Safari and it works like a charm. Great stuff.

  28. spidoxxxx
    Permalink to comment#

    so cool !!! Thanks

  29. Permalink to comment#

    Thanks for this. I am testing it out and thinking about implementing it at http://familylegacy.com/home-test-page/

  30. Permalink to comment#

    Responsive all the way down until mobile css version.
    < http://www.pushinpixels.co.uk/portfolio.html >
    Mobile version another day.

    KEEP DANCING…

  31. rgregory
    Permalink to comment#

    I would love to see the little chunk of WordPress loop code and the subtle changes in the jQuery that would make this work in WP.

    Any talented folks out there with a benevolent streak?

  32. Permalink to comment#

    Oooh that’s fun! This gave me a few ideas for some existing projects. … This is the first time I have seen your site too. I like all the details. The icons in the name, email and website fields for comments is very cool as is the background that animates in the comments area. You just got a new follower! :-) Thanks.

  33. Nice and simple…! best part is no complications. bundled basic things together…
    well done

  34. That is just too much fun. Wow, it’s magic. Thanks.

  35. Permalink to comment#

    Would love it if you make a post about making the slides changes after specified duration.

    Then this could be used as replacement today-popular jQuery sliders used to show content & images..

  36. Steve Kolan
    Permalink to comment#

    Does anyone think the custom layout animation effect like this site has would be possible with today’s HTML/CSS/jQuery capabilities?

    http://www.hybridworks.jp/

  37. Man, you got an amazing sense of creativity, like that of an artist, with the finesse of a good web developer!

  38. Permalink to comment#

    This is great and you have such a useful/user friendly site. I implemented the boxes here. http://www.designsourced.com .
    Thanks again!

  39. Permalink to comment#

    Hi, thanks for this tutorial!
    The rotator has a fixed height here, is there any possibility in CSS to adapt the height to the content?

  40. Permalink to comment#

    Thx again Css-tricks, i implement the box on my articles page,
    Rotating blocks

    and modified it to work with php and mysql see what line i’ve change
    here

    thx again….

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".