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.
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.
*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.
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!
Firefox Beta 9 contains many new Html5 and CSS3 features which were missing in previous release.
http://hacks.mozilla.org/2011/01/firefox-4-beta-9-a-huge-pile-of-awesome/
Dance! Dance Magic Dance!
Good one chris…:)
Keep going…:)
Awesome!
Can we name this trick the “do-si-do”?
microsoft also did something similar
http://www.beautyoftheweb.com/#/highlights/all-around-fast
Okay — Microsoft EPIC’ed it. DAMN!
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.
I couldn’t stop clicking!
Woosh ! that’s a really cool effect ! Thanks :)
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.
Cool effect, but a total usability no-no IMHO.
I’m curious as to what would deem this “a total usability no-no”
I agree. It’s just a gimmick.
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.
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.
LABRYNTH!!!!!!!!!!!!!! Nice.
Very cool Chris =)
Chris, are you saying that other things equal, CSS > JavaScript for any animation?
Yes.
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.
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>
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.
Doesn’t work in IE :(
Love it.. After these effects flash will obviously go down..
For some reason Safari 5.0.3 for Leopard does not display the #1 text and image. Only the empty blue box. Any ideas?
see Piers‘s comment above:
Great effect.
I can’t get ANY of the wonderful stuff on this site to work with squarespace :( :(
Beautiful, i surely will use this one, thanks!
i dont know what to say…
I love this website Chris…
Professional web developers cater for browsers that have JavaScript turned off. Anyone who doesn’t is an amature.
Yes, because most companies don’t take into account the web analytics and target audience.
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!
Flash is becoming a thing of the past!
At first it was just a cool effect… then the Labyrinth quote popped up and it suddenly evolved into “legendary”
Thanks for sharing.
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.
so cool !!! Thanks
Thanks for this. I am testing it out and thinking about implementing it at http://familylegacy.com/home-test-page/
Responsive all the way down until mobile css version.
< http://www.pushinpixels.co.uk/portfolio.html >
Mobile version another day.
KEEP DANCING…
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?
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.
Nice and simple…! best part is no complications. bundled basic things together…
well done
That is just too much fun. Wow, it’s magic. Thanks.
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..
Hey all,
I absolutely love this “trick” and I had to mess around with it. Here’s what I came up with:
CSS3 Animations Demo
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/
Man, you got an amazing sense of creativity, like that of an artist, with the finesse of a good web developer!
This is great and you have such a useful/user friendly site. I implemented the boxes here. http://www.designsourced.com .
Thanks again!
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?
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….
After seeing this, I was inspired to make my own (IMO cooler) version. While I have a lot of experience with CSS transitions, this was too complicated to make with CSS as I’m doing multiple animations on the same element at once and instantly changing some CSS properties. It’s hard to explain, so you’ll just have to try it yourself