3D Thumbnail Hover Effects

A tutorial about how to create 3D thumbnail hover effects with CSS 3D transforms and jQuery.

3d Thumbnail Hover Effects

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.

Please note: the result of this tutorial will only work as intended in browsers that support the respective CSS properties.

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>

		<img src="images/1.jpg" />


	<div class="view">

	<!-- ... -->


	<!-- ... -->

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 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.


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!


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.

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

πŸ‘Ύ Hey! Looking for the latest in frontend? Twice a week, we'll deliver the freshest frontend news, website inspo, cool code demos, videos and UI animations right to your inbox.

Zero fluff, all quality, to make your Mondays and Thursdays more creative!

Feedback 110

Comments are closed.
  1. Really great!
    I want to use this effect on a image that is 980×400 px. How do I change the the size in the css?

    Thank you for a great work!!

    • Hi Marcus, you will need to adjust the width/height of the view, the width of the slice, the overlay (image width divided by 5), the translate3d values and the background positions of the single slices. I’ve uploaded another demo (demo 5, ZIP file is also updated) with a 980Γ—400px image. The perspective value for the view should also be adjusted. Hope it helps, cheers, ML

  2. Great, awesome plugin i search from last two week,
    really i found on your site great work,

  3. I was trying to mix it up with fancybox on click galery. And yes it works but thumbnails always are on top even .view z-index is lower than fancybox content. Can some1 help me with this?

  4. And i found bug only in chrome when u hover many times this thumbnails u get this – screen. greetings

    • I check it on all browsers, on safari it works the best. on chrom only first 1 thumbnail works , rest like on screen. Opera and firefox dont work at all. But on firefox from this tutorial worked. So it is not done yet think so. And im using Windows 7:).
      I’m looking for bugs and shortcomings to improve your great hover effect. Pozdrawiam πŸ™‚

  5. Dear MARY LOU

    I like your tutorial so much it give me inspiration to work but,
    I want it to open from left to right (ref.demo2) I tried to edit some CSS but it’s not work.
    can I have any suggestion from you.

    thank you so much


  6. First of all: WOW! Very nice!

    But, I have a problem.
    I can’t get demo 2 working.
    I guess I have to change the style_common.css, but I just don’t know how 😐
    Please help me!


  7. Hii!

    First of all: GREAT demo! The effect off 3D css is awesome.

    But can you help me out? I’ve tried your demo on: http://temp.gijsjager.nl.
    But it seems to have a bug wich your demo hasn’t.

    When I hover my elements sometimes the in the other elements objects dissapear. It almost looks like a browser faulty.
    I can’t seem to figure out why it does that.
    Also when I use the perspective of 500px, I can’t hover on the items behind the image that folds. When I set the perspective to an awesome 20.000px :)) it fixes the problem.

    I hope you have the time to help me out!

  8. I am having the same problem as Gijs is. When I hover over certain objects others seem to disappear. Please a little help here?

    Other then that I really do love this hover.

  9. Using Demo 2… Everything works but my last slice is identical to the first slice. Any ideas where it’s gone wrong?

  10. Interesting… you think it could be used on production sites and limit availability with modernizr (as to only trigger the effect if certain requirementes are made, i’m guessing css 3d transforms)

    Gonna start experimenting, thanks a lot.

  11. To anyone wondering why the downloaded demo doesn’t work like the demo on this site, it’s because of:

    .main {
    overflow: hidden; }

  12. This is really nice! I was a bit disappointed at the lack of documentation on exactly what properties needed to be changed to adjust the width of the image container. Also, if you’re experiencing quirks after downloading the demo files, it’s because the overflow on div.main is set to hidden, which causes a bug when hovering.

  13. Hi Mary Lou !

    Great tuto as usual, this kind of little animation are a efficient way to create a good UX !

    As many people who commented before me, i have a problem with the code for the “Demo 2”

    At the end of your code there is a link to ‘css/fallback.css’, and when i change it to link it to the one on my server the code is not working anymore as it works on Dreamweaver.

    test: Modernizr.csstransforms3d && Modernizr.csstransitions,
    yep : [‘js/jquery.hoverfold.js’],
    nope: ‘css/fallback.css’,
    callback : function( url, result, key ) {

    Do you have any advice please ?

  14. Hi i am trying to implement this GREAT!!!! CSS script in my web site but i can not make it work in Chrome! It is working perfect in SAFARI & FIREFOX but in chrome always the first div is doing crazy stuff!

    i have them all i one gallery row with no margins left or right! STYLE1 is that i am trying to get working

    here is the HTML markup







    • This won’t work on IE 6,7,8 (no CSS3 support), 9 (no css3 3d transform support).

      This code works partially in IE 10, with some optimization it might work.

  15. What a fun little piece of code! I’m putting together a little version of this that’ll work in WordPress based on user generated settings and some simple JS/PHP to generate the 3D transition values dynamically based on their desired width/height. Here’s a preview of mine in progress: http://kollection.mdnw.net

  16. Hi guys! I’m working on my web site and using your wonderful 3D Thumbnail Hover Effects. It’s amazing. And thank you for that. But are there any ways to use effect by vertical (not horizontal as now)? My images have 200px wide and after hover there isn’t enough space for text in right. And I want to show it in bottom. How do you think?

  17. hiiii guys!!! I am new in website design field. I am trying to use it, but it’s not working.
    could you plz tell me the exact codes which I should put in the html tag….

  18. This is really sweet!
    We are trying to figure out how to do a number of these sized differently (120×120 px, 180x180px). We can’t get the overlays to position. How do we get the view div to also translate to the overlays and slices?

    thanks again!

    • im actually doing this right now – shadowbox is the only one i found that actually works with this

  19. Thanks for this brilliant work! It looks amazing!
    I am eager to know are there any possible hacks to make this outstanding thing work in the old versions of browsers, and especially our “very much loved” IE.
    Well, I mean is it possible to write some Javascript that will be used only by the browsers that can’t see these effects?

  20. Hello everyone i love this effect, there is one little problem im running into.
    I have 4 images right now right out of the example and 2 of them do not open to 50% one is about 30% the other one is about 10% cant even see the link any ideas?

  21. This is really awesome! I’m having trouble changing the direction of the animation though, any tips?