From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
Today we want to show you how to create some exciting 3D hover effects using CSS3 and jQuery. This idea is inspired by the cool hover effect that you can find on the page of the Google SketchUp Showcase.
In our examples, we’ll use thumbails that will reveal some more information on hover. We will create a structure with jQuery that will allow making the image appear as folded or bended when we hover over it. For the hover effects we will use CSS 3D transforms.
The images used in the demos are by Angelo Gonzรกlez and they are licensed under the Creative Commons Attribution 2.0 Generic (CC BY 2.0) License.
We will omit vendor prefixes in this tutorial. But you’ll of course find them in the files.
The Markup
The markup for the thumbnail structure will be as follows:
<div id="grid" class="main"> <div class="view"> <div class="view-back"> <span data-icon="A">566</span> <span data-icon="B">124</span> <a href="http://www.flickr.com/photos/ag2r/5439506585/in/photostream">โ</a> </div> <img src="images/1.jpg" /> </div> <div class="view"> <!-- ... --> </div> <!-- ... --> </div>
Each thumbnail goes into a division with another division for the details (view-back). The structure that we want to create for each division with the class view using JavaScript is the following:
<div class="view"> <div class="view-back"> <!-- ... --> </div> <div class="slice s1" style="background-image: url(images/1.jpg); "> <span class="overlay"></span> <div class="slice s2" style="background-image: url(images/1.jpg); "> <span class="overlay"></span> <div class="slice s3" style="background-image: url(images/1.jpg); "> <span class="overlay"></span> <div class="slice s4" style="background-image: url(images/1.jpg); "> <span class="overlay"></span> <div class="slice s5" style="background-image: url(images/1.jpg); "> <span class="overlay"></span> </div><!-- /s5 --> </div><!-- /s4 --> </div><!-- /s3 --> </div><!-- /s2 --> </div><!-- /s1 --> </div><!-- /view -->
Each slice will have the respective image as it’s background image and since we have a nested structure, this will allow us to control the effect. Additionally, we’ll add an overlay span that we’ll use to make the effects more realistic.
Our JavaScript function looks as follows:
$.fn.hoverfold = function( args ) { this.each( function() { $( this ).children( '.view' ).each( function() { var $item = $( this ), img = $item.children( 'img' ).attr( 'src' ), struct = '<div class="slice s1">'; struct +='<div class="slice s2">'; struct +='<div class="slice s3">'; struct +='<div class="slice s4">'; struct +='<div class="slice s5">'; struct +='</div>'; struct +='</div>'; struct +='</div>'; struct +='</div>'; struct +='</div>'; var $struct = $( struct ); $item.find( 'img' ).remove().end().append( $struct ).find( 'div.slice' ).css( 'background-image', 'url(' + img + ')' ).prepend( $( '<span class="overlay" ></span>' ) ); } ); }); };
Now we can have a lot of hover fun! Let’s first define some common styles and then we’ll go through the first example.
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
The CSS
Let’s define the style for the view divisions. What’s important here is that we add perspective:
.view { width: 316px; height: 216px; margin: 10px; float: left; position: relative; border: 8px solid #fff; box-shadow: 1px 1px 2px rgba(0,0,0,0.05); background: #333; perspective: 500px; }
The slices will need some 3D properties and a transition:
.view .slice{ width: 60px; height: 100%; z-index: 100; transform-style: preserve-3d; transform-origin: left center; transition: transform 150ms ease-in-out; }
The part of the description that get’s revealed when we push the slices to the side will have the following style:
.view div.view-back{ width: 50%; height: 100%; position: absolute; right: 0; background: #666; z-index: 0; }
Let’s style the spans and the link:
.view-back span { display: block; float: right; padding: 5px 20px 5px; width: 100%; text-align: right; font-size: 16px; color: rgba(255,255,255,0.6); } .view-back span:first-child { padding-top: 20px; } .view-back a { display: bock; font-size: 18px; color: rgba(255,255,255,0.4); position: absolute; right: 15px; bottom: 15px; border: 2px solid rgba(255,255,255,0.3); border-radius: 50%; width: 30px; height: 30px; line-height: 22px; text-align: center; font-weight: 700; } .view-back a:hover { color: #fff; border-color: #fff; }
For the icon before the spans we’ll use an icon font that we’ve created with Fontello. Since we have added a data-icon attribute to the spans, we can use the pseudo-class :before to display it:
.view-back span[data-icon]:before { content: attr(data-icon); font-family: 'icons'; color: #aaa; color: rgba(255,255,255,0.2); text-shadow: 0 0 1px rgba(255,255,255,0.2); padding-right: 5px; }
All, except the first slice, need to be moved to the right (remember, we have a nested structure):
.view .s2, .view .s3, .view .s4, .view .s5 { transform: translateX(60px); }
Let’s set the respective background positions of each slice for the background image:
.view .s1 { background-position: 0px 0px; } .view .s2 { background-position: -60px 0px; } .view .s3 { background-position: -120px 0px; } .view .s4 { background-position: -180px 0px; } .view .s5 { background-position: -240px 0px; }
The overlays will initially have an opacity of 0 and we’ll add a transition and change the opacity level on hover:
.view .overlay { width: 60px; height: 100%; opacity: 0; position: absolute; transition: opacity 150ms ease-in-out; } .view:hover .overlay { opacity: 1; }
Let’s just fix the position and z-index for the image (just so that we don’t see the back part on top and for the fallback). And we’ll also add a transition for browsers that don’t support 3D transforms:
.view img { position: absolute; z-index: 0; transition: left 0.3s ease-in-out; }
In case we see that a browser does not support all those fancy 3D properties, we’ll simply load an additional stylesheet called fallback.css which will have the following content:
.view { overflow: hidden; } .view:hover img { left: -85px; } .view div.view-back { background: #666; }
This will make the image slide to the left when we hover.
Now, let’s take a look at the example!
Example
For this example we will want to create a folding effect. For that we’ll adjust the perspective value of the view division and the transition for all the divisions:
.view { perspective: 1050px; } .view div { transition: all 0.3s ease-in-out; }
The second, third, forth and fifth slice will be translated and rotated in 3D, creating the fold effect:
.view:hover .s2{ transform: translate3d(59px,0,0) rotate3d(0,1,0,-45deg); } .view:hover .s3, .view:hover .s5{ transform: translate3d(59px,0,0) rotate3d(0,1,0,90deg); } .view:hover .s4{ transform: translate3d(59px,0,0) rotate3d(0,1,0,-90deg); }
Each of these slices will be moved to the left. It should be the value of their widths but we want to avoid showing a little gap, so we use 59px. The second slice will be rotated -45 degrees, making it turn towards the left. The forth slice rotates the other way and the third and fifth will both rotate 90 degrees. Remember, we are in a nested structure. Once we rotate a parent, the children will all be rotated.
To make things look a bit more realistic, we’ll add some gradients to the overlays:
.view .s2 > .overlay { background: linear-gradient(right, rgba(0,0,0,0.05) 0%,rgba(0,0,0,0) 100%); } .view .s3 > .overlay { background: linear-gradient(left, rgba(255,255,255,0) 0%, rgba(255, 255, 255, 0.2) 100%); } .view .s4 > .overlay { background: linear-gradient(right, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%); } .view .s5 > .overlay { background: linear-gradient(left, rgba(0,0,0,0.8) 0%,rgba(0,0,0,0) 100%); }
The detail part of the thumbnail that get’s revealed when we hover, will also have a background gradient, since we want to simulate a shadow falling on it:
.view div.view-back{ background: linear-gradient(left, #0a0a0a 0%,#666666 100%); }
And that’s it! Check out the other examples and go nuts! There are many different possibilities for fooling around with this.
I hope you find it inspiring!
Check out Richard Bennett’s version that works on a click/touch event.
Great!
Thanks Mary
I love your work <3
spectacular demo! Great tut ๐
Cheers
This sicks Mary .Thank you for the great tutorial ๐
This is pretty awesome thanks for sharing.
exceptional!!!!! simply amazing,keep posting:)
wow this is incredible, thanks for the great tutorial, your tut series is one of the best CSS lessons I’ve read
nice like always mary lou, is it working on major browsers ?…
Gracias, no era fรกcil ver la potencia del css3 por este lado. Great tutorial! ๐
WOW perfect… I love this recipe… ;D
Wow fantastic! Thx for the tutorial ๐
ABSELOUTLY AMAZING *___________________*
Codrops contains so much amazing hover effects, now i don’t know which i wanna use in my site ๐
yeah !
OMG, nice job ! love it ^^
this is f***ing amazing ! no way… absolutly fantastic !!!
congratulations !
woW Super efect
Thank you.
I can never get bored of the effects and tutorials you do Mary! You are very great so keep it up ๐
That’s it, there’s no dispute anymore: You’re the queen of CSS along with Rachel Andrew. What’s your advice on polyfilling this solution using modernizer?
Holy kittens, this is awesome!!!
Thank you. much appreciated.
Excellent work! very beautifull effects! you’r the best ^^
Thank you all for your great feedback, I’m really glad you like it!!!
Hi Mary Lou
Before reading this article I was not aware of the 3d hover effects on the Google Sketch up page. The effect you have used in this tutorial is very effective without over complicating the design, as is the side bar open paper effect also used on the Sketch up website.
Cathy
I’m using Chrome latest; all the demos look identical to me :-/
That’s because Google Chrome gives a false negative. It’s because Modernizr uses media queries in its tests. That queries sometimes fails in some chrome versions.
As in this tutorial JS is conditionally loaded via
Modernizr.load
, it doesn’t load it and it loads the fallback CSS.More info:
Chrome bug
Issue on Github
While I prefer firefox, they suck with render. Chrome is much better
gr8 demo… U r awesome as always…
Great tutorial. I’d love to get this effect (specifically the page roll in Demo 2 or 3) triggered on a touch event in Mobile Safari.
I should clarify though – I don’t recall if Mobile Safari supports 3D transforms, however… LOL
what about noscript freaks, as I am kind of oldtimer I like to see graceful degradation for all possible cases. shure it’s propably 1% but still. And of course it just matter of some markup changes so it may be I’m just babbling because of heat… sorry…
Wha-ou.
Again : wha-ou
That’s really beautiful. Just one problem, it’s not very anti-aliased on Firefox or Safari for Windows.
Awesome effect. I have to compliment you, one of the best website with web dev and web design tutorials. Keep doing great works Mary ๐
There is a problem on chrome when it comes to the link toward flickr. In demo #1, you have the problem on both right “views” while it works on the left column. The problem is that you cant mouseover the block element. Seems like “view” is above the link and that stops you from being able to use it 100%. It does work on the far right of the link element, but the area is very small.
The fix to this problem is to just decrease the .view:hover translate3d!
Amazing effects! Keep up the great work!
I found this on dribbbble a few minutes ago and thought it looked familiar. This article is 24 hours before the dribbble post. I didn’t see any credits on either site. It could just be a huge coincidence though…
http://drbl.in/esfe
Yeah, huge coincidence ๐ at least he could have changed the numbers… ๐
Oh now that’s just terrible.
Great tut mary, tnx alot ๐
Nice!
Nothing its just awesome ๐
YAY!
I got the tutorial above (Demo 2, specifically) working on a click/touch event. I just downloaded the Demo source and modified the HTML/CSS a tad. Mary Lou, if you’d like a copy, I can post it somewhere. I’m sure there’s a more efficient way of doing it, but I essentially removed references to “.view:hover” and created a new “.touched” class that is toggled to all DIV.view elements when clicked/touched.
That’s absolutely great! If you put it online somewhere I’ll be happy to link to it; I’m sure many mobile developers will find it really helpful! Thanks, cheers, ML
I sent you a note on G+ with the URL. Feel free to do with what you with – it’s your hard work after all! ๐
For whatever reason, it’s not working in my version of Google Chrome. I’m running 19.0.1084.56 beta-m on Windows 7 Ultimate. Is this a bug?
I get part of the transition on the lower right hand side of the image, but anything above that doesn’t work.
Wicked! Thank you.
If I were going to use it on images that are 900×600 in size, how would I change the numbers?
Aaah Mary Lou great demo as always I think I’m in love ๐
I think this is awesome, and looks great, but really struggling with the role of hover related effects on todays web. With so much traffic now coming from touch related devices, what does this mean for hover type effects?
Never seen such great effect. Amazing use of CSS
It is very unique- I have not seen this before- thank you
this is a fantastic work ! thank very much sharing with us ((:
too late for comments ๐
fantastico fantastico…bravo bravo
keep posted Mary Lou and keep your health ๐
awesome
Wow! Awesome paper-fold effect โย And much wider browser support than I thought there’d be.
Great tutorial. Keep up the fantastic work!
This looks amazing in FireFox 15. So smooth!
Wow, excellent effect ๐
this looks great! although it’s a pretty playful kinda thingy.
I’m kinda stunned by the The Markup – part of the tut.. It’s so much input.. jesus… my brainz
First time I saw it I was in love with this effect, thank you very much!