From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
In the following tutorial we will create an asymmetrical image slider with a little twist: when sliding the pictures we will slightly rotate them and delay the sliding of each element. The unusual shape of the slider is created by some elements placement and the use of thick borders. We will also add an autoplay option and the mousewheel functionality.
We’ll use the jQuery 2D Transformation Plugin for rotating the images and the jQuery Mousewheel Plugin by Brandon Aaron for the mousewheel control.
The beautiful photos are by Andrew and Lili and you can see their Behance profile here:
http://www.behance.net/AndrewLili
The images are licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License.
Allrighty! Let’s start with the HTML!
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 Markup
First, we will wrap all our slider elements in a wrapper with the class “rm_wrapper”:
<div class="rm_wrapper"> ... </div>
Inside of that wrapper we will have a container for the actual slider list, some mask and corner elements, the heading and a hidden div that will contain all the image sets:
<div id="rm_container" class="rm_container"> <ul> <li data-images="rm_container_1" data-rotation="-15"> <img src="images/1.jpg"/> </li> <li data-images="rm_container_2" data-rotation="-5"> <img src="images/2.jpg"/> </li> <li data-images="rm_container_3" data-rotation="5"> <img src="images/3.jpg"/> </li> <li data-images="rm_container_4" data-rotation="15"> <img src="images/4.jpg"/> </li> </ul> <div id="rm_mask_left" class="rm_mask_left"></div> <div id="rm_mask_right" class="rm_mask_right"></div> <div id="rm_corner_left" class="rm_corner_left"></div> <div id="rm_corner_right" class="rm_corner_right"></div> <h2>Fashion Explosion 2012</h2> <div style="display:none;"> <div id="rm_container_1"> <img src="images/1.jpg"/> <img src="images/5.jpg"/> <img src="images/6.jpg"/> <img src="images/7.jpg"/> </div> <div id="rm_container_2"> <img src="images/2.jpg"/> <img src="images/8.jpg"/> <img src="images/9.jpg"/> <img src="images/10.jpg"/> </div> <div id="rm_container_3"> <img src="images/3.jpg"/> <img src="images/11.jpg"/> <img src="images/12.jpg"/> <img src="images/13.jpg"/> </div> <div id="rm_container_4"> <img src="images/4.jpg"/> <img src="images/14.jpg"/> <img src="images/15.jpg"/> <img src="images/16.jpg"/> </div> </div> </div>
So the unordered lists will have the first set of four images where each list element has some data attributes for the image sets and the rotation degree. We will use that data to know which images come next and how much each image should be rotated.
The mask and corner divs will be absolute elements that we will place on top of the slider, slightly rotated in order to cover some areas. Since we will use the same background color for these elements like the body’s background color, we will create the illusion of the images being shaped in a certain way.
Then we’ll add the elements for the navigation and the autoplay controls:
<div class="rm_nav"> <a id="rm_next" href="#" class="rm_next"></a> <a id="rm_prev" href="#" class="rm_prev"></a> </div> <div class="rm_controls"> <a id="rm_play" href="#" class="rm_play">Play</a> <a id="rm_pause" href="#" class="rm_pause">Pause</a> </div>
Let’s take a look at the CSS.
The CSS
First, we’ll reset some styles and define the properties for the body. (Remember, if we would have another background color, we would want to change the background and border colors of some of the elements in our slider, too.)
@import url('reset.css'); body{ background:#f0f0f0; color:#000; font-family: 'PT Sans Narrow', Arial, sans-serif; font-size:16px; } a{ color:#000; text-decoration:none; } h1{ padding:10px; margin:20px; font-size:40px; text-transform:uppercase; text-shadow:0px 0px 1px #fff; color:#333; background:transparent url(../images/line.png) repeat-x bottom left; }
The main wrapper will have the following style:
.rm_wrapper{ width:1160px; margin:0 auto; position:relative; }
The container for the slider will have any overflow hidden, which will help shaping our slider since we will cut off the outer sides of it:
.rm_container{ width:1050px; overflow:hidden; position:relative; height:530px; margin:0 auto; }
The heading will have the following style:
.rm_container h2{ background:transparent url(../images/lines.png) repeat top left; padding:10px 30px; position:absolute; bottom:170px; right:0px; color:#000; font-size:36px; text-transform:uppercase; text-shadow:1px 0px 1px #fff; }
Let’s define the width for the ul to be bigger than the container since we want to make the list element float next to each other:
.rm_container ul{ width:1170px; }
By giving a negative left margin and a thick border to the list element, we will overlap the images and cut off the right sides so that we create our asymmetrical shapes by rotating the elements then. The border color will be the same like the background color of the body (or the container).
.rm_container ul li{ float:left; margin-left:-80px; position:relative; overflow:hidden; width:310px; height:465px; border:30px solid #f0f0f0; border-width:50px 30px 0px 30px; background-color:#f0f0f0; }
We’ll position the images absolutely:
.rm_container ul li img{ position:absolute; top:0px; left:0px; }
In the following we will style the mask and the corner elements. They will be all positioned absolutely and we’ll give them the grey background color. By rotating them, we’ll make the images to appear as being “shaped”:
.rm_mask_right, .rm_mask_left{ position: absolute; height: 110px; background: #f0f0f0; width: 530px; bottom: -30px; left: 0px; -moz-transform:rotate(-3deg); -webkit-transform:rotate(-3deg); transform:rotate(-3deg); } .rm_mask_right{ left:auto; right:0px; -moz-transform:rotate(3deg); -webkit-transform:rotate(3deg); transform:rotate(3deg); } .rm_corner_right, .rm_corner_left{ background: #f0f0f0; position:absolute; width:200px; height:100px; bottom:0px; left:-65px; -moz-transform:rotate(45deg); -webkit-transform:rotate(45deg); transform:rotate(45deg); } .rm_corner_right{ left:auto; right:-65px; -moz-transform:rotate(-45deg); -webkit-transform:rotate(-45deg); transform:rotate(-45deg); }
The navigation elements will be placed to the left and right of the main container:
.rm_nav a{ position:absolute; top:200px; width:38px; height:87px; cursor:pointer; opacity:0.7; } .rm_nav a:hover{ opacity:1.0; } .rm_nav a.rm_next{ background:transparent url(../images/next.png) no-repeat top left; right:0px; } .rm_nav a.rm_prev{ background:transparent url(../images/prev.png) no-repeat top left; left:0px; }
The pause/play control will be placed to the top left of the main container:
.rm_controls{ position:absolute; top:0px; left:-40px; height:20px; } .rm_controls a{ cursor:pointer; opacity:0.7; padding-left:24px; font-size:16px; text-transform:uppercase; height:20px; float:left; line-height:20px; } .rm_controls a:hover{ opacity:1.0; } .rm_controls a.rm_play{ display:none; background:transparent url(../images/play.png) no-repeat center left; } .rm_controls a.rm_pause{ background:transparent url(../images/pause.png) no-repeat center left; }
And that’s all the style! Let add the spice!
The JavaScript
The main idea for the slider functionality is to add another image before the current one with a slightly increased rotation degree than the current item. Then we will animate the rotation and make the new images appear.
So let’s start by caching some elements and checking if we are dealing with a special needs browser in order to deal with some issues:
//our 4 items var $listItems = $('#rm_container > ul > li'), totalItems = $listItems.length, //the controls $rm_next = $('#rm_next'), $rm_prev = $('#rm_prev'), $rm_play = $('#rm_play'), $rm_pause = $('#rm_pause'), //the masks and corners of the slider $rm_mask_left = $('#rm_mask_left'), $rm_mask_right = $('#rm_mask_right'), $rm_corner_left = $('#rm_corner_left'), $rm_corner_right= $('#rm_corner_right'), //check if the browser is <= IE8 ieLte8 = ($.browser.msie && parseInt($.browser.version) <= 8),
Then we will define our main function:
RotateImageMenu = (function() { ... })(); RotateImageMenu.init();
And then we define the following in our function:
//difference of animation time between the items var timeDiff = 300, //time between each image animation (slideshow) slideshowTime = 3000, slideshowInterval, //checks if the images are rotating isRotating = false, //how many images completed each slideshow iteration completed = 0, /* all our images have 310 of width and 465 of height. this could / should be dynamically calculated if we would have different image sizes. we will set the rotation origin at x = width/2 and y = height*2 */ origin = ['155px', '930px'], init = function() { configure(); initEventsHandler(); }, //initialize some events initEventsHandler = function() { /* next and previous arrows: we will stop the slideshow if active, and rotate each items images. 1 rotate right -1 rotate left */ $rm_next.bind('click', function(e) { stopSlideshow(); rotateImages(1); return false; }); $rm_prev.bind('click', function(e) { stopSlideshow(); rotateImages(-1); return false; }); /* start and stop the slideshow */ $rm_play.bind('click', function(e) { startSlideshow(); return false; }); $rm_pause.bind('click', function(e) { stopSlideshow(); return false; }); /* adds events to the mouse and left / right keys */ $(document).bind('mousewheel', function(e, delta) { if(delta > 0) { stopSlideshow(); rotateImages(0); } else { stopSlideshow(); rotateImages(1); } return false; }).keydown(function(e){ switch(e.which){ case 37: stopSlideshow(); rotateImages(0); break; case 39: stopSlideshow(); rotateImages(1); break; } }); }, /* rotates each items images. we set a delay between each item animation */ rotateImages = function(dir) { //if the animation is in progress return if(isRotating) return false; isRotating = true; $listItems.each(function(i) { var $item = $(this), /* the delay calculation. if rotation is to the right, then the first item to rotate is the first one, otherwise the last one */ interval = (dir === 1) ? i * timeDiff : (totalItems - 1 - i) * timeDiff; setTimeout(function() { //the images associated to this item var $otherImages = $('#' + $item.data('images')).children('img'), totalOtherImages = $otherImages.length; //the current one $img = $item.children('img:last'), //keep track of each items current image current = $item.data('current'); //out of bounds if(current > totalOtherImages - 1) current = 0; else if(current < 0) current = totalOtherImages - 1; //the next image to show and its //initial rotation (depends on dir) var otherRotation = (dir === 1) ? '-30deg' : '30deg', $other = $otherImages.eq(current).clone(); //for IE <= 8 we will not rotate, //but fade out / fade in ... //better than nothing :) if(!ieLte8) $other.css({ rotate : otherRotation, origin : origin }); (dir === 1) ? ++current : --current; //prepend the next image to the <li> $item.data('current', current).prepend($other); //the final rotation for the current image var rotateTo = (dir === 1) ? '80deg' : '-80deg'; if(!ieLte8) { $img.animate({ rotate : rotateTo }, 1200, function(){ $(this).remove(); ++completed; if(completed === 4) { completed = 0; isRotating = false; } }); $other.animate({ rotate : '0deg' }, 600); } else { $img.fadeOut(1200, function(){ $(this).remove(); ++completed; if(completed === 4) { completed = 0; isRotating = false; } }); } }, interval ); }); }, //set initial rotations configure = function() { if($.browser.msie && !ieLte8) rotateMaskCorners(); else if(ieLte8) hideMaskCorners(); $listItems.each(function(i) { //the initial current is 1 //since we already showing the first image var $item = $(this).data('current', 1); if(!ieLte8) $item.transform({rotate: $item.data('rotation') + 'deg'}) .find('img') .transform({origin: origin}); }); }, //rotates the masks and corners rotateMaskCorners = function() { $rm_mask_left.transform({rotate: '-3deg'}); $rm_mask_right.transform({rotate: '3deg'}); $rm_corner_left.transform({rotate: '45deg'}); $rm_corner_right.transform({rotate: '-45deg'}); }, //hides the masks and corners hideMaskCorners = function() { $rm_mask_left.hide(); $rm_mask_right.hide(); $rm_corner_left.hide(); $rm_corner_right.hide(); }, startSlideshow = function() { clearInterval(slideshowInterval); rotateImages(1); slideshowInterval = setInterval(function() { rotateImages(1); }, slideshowTime); //show the pause button and hide the play button $rm_play.hide(); $rm_pause.show(); }, stopSlideshow = function() { clearInterval(slideshowInterval); //show the play button and hide the pause button $rm_pause.hide(); $rm_play.show(); }; return {init : init};
As you noticed, we will treat older browsers a bit differently so that the slider works properly.
And that’s it! We really hope you enjoyed the tutorial and like the result!
Very nice, but unfortunately doesn’t work on Chrome 12 but does work on Chromium 13.
this is just AWESOME
That’s a awesome slideshow, would be useful for nearly any photography or design portfolio.
Doesn’t work properly on Opera 10.11
First this slide show is amazing!!
I am working it into a minimalist design page right now. The problem I have is that I have a nav menu (made from simple unordered list) at the top of the page. For some reason, the nav menu is rendered unclickable with something in the style sheet you provided. There isn’t anything wrong with the nav menu because it works on all the other pages and it works if I disable the style sheet you provided. I have searched through there and can’t find any class or id that would be disabling links. Very frustrated and would great appreciate any help or pointers if you have them? Also has anyone else experienced this issue? P.S. It is not browser specific issue. Same in Opera,Chrome, IE,FF, and Safari
My sincere apologies!
I meant to post this in the comment thread at this page:
http://tympanus.net/codrops/2010/10/07/slider-gallery/
And I fixed the issue just now. Posted my menu outside of the proper div container.
Kudos again to the amazing Jquery work you have!
This is super duper cool! Very different and not boring. I should have seen this before starting my project! it’s never too late tho. 🙂 thanks for this!
No Images with Google Chrome!
hi mary, can you tell me how i have to change the javascript so that the slideshow works always as the IE-Version? No rotatition but fade-effect and no rotatet images. That would be nice. kind regards,
christin
I don’t know what all you Chrome yuppies are complaining about. I am using Google Chrome and I can see the images and everything works just fine. Maybe you have some plugins enabled which are causing them to not show up!
wonderful slider good work…
with all the css3 why not use image masks too? Or at least add the masks via JS unobtrusively..?
Really nice, wonderful work.
Very cool Slideshow! Well done! How to do an autoplay onload?
This is the best image slider I have come across. One question though, is it possible to add captions to each slide?
Hi Mary, How do you get it to autoplay on load. Ryt now it seems to be fixated on ‘click’ handler. Am not that good with jquery yet.
Hi mary Lou … Great piece of Work … I would like to use together with prettyphoto , but when i add the Hyperlink instead of the img … it does not work .. Any suggestions?
Thanks
how to let this web autoplay the slideshow when I just go this web without to click play~??thanks
very useful..thank u very much
Very nice. Any chance of being able to make the image clickable? And/or a fancy tooltip with a link in it?
Ones again, THANK YOU for a more then perfect application!!!!
Great work as always Mary Lou!
I’ve seen some people have the same question as I do, but haven’t seen a reply yet.
I would like the slideshow to automatically start when the page loads, how can I achieve this?
Does anyone have the answer?
thanks!!
Marry
I try to put this slider into a test page, but I’ve noticed that, the page scrollbar became unusable.
how to make the scrollbar work ? please advise
You guys always do some breathtaking tutorials..props!
i’ll try to implement this slider for sure.
Great and mind-blowing…
Hey,
I am not able to manage to get links to pictures. How do I fix this?
If you guys want to autoplay this on page load, you can put:
startSlideshow();
directly before:
return {init : init};
Not the best the way to do it, but it works.
Cheers.
how can I add more pictures?
very nice, but how to show images from from mysql database, any help?
Hi, it woks perfect, but if i load MODERNIZR (basic), it stops working on Firefox!
Does anybody has an idea about this problem?
Really thanks for the tutorial Mary Lou, its amazing!
Just thought I’d mention that your slider is now being sold in a theme over at Themeforest.
http://themeforest.net/item/suerte-premium-corporate-portfolio-wp-theme/386090
I only bring this up since I’ve had my work taken and sold and I wasn’t really all that cool with it happening.
Maybe you don’t care but I figured I’d at least tell you in case you DO care.
Hi, i’m the author who sell the Suerte theme, with this slider.
Before to integrate your slider in my WordPress theme i saw your copyright page (now you replaced it?) where you said that we are free to use your works also in commercial project, but we have to give you credits for your work.
In my themeforest page, in the description of the theme, i write “Rotating slider: thanks to Tympanus.net (with link to this page)
The beautiful photos are by Andrew and Lili and you can see their Behance profile here: http://www.behance.net/AndrewLili”
I provided credits to you and to photo’s author.
Let me know if it’s an problem for you. Thank you S.
Hi Sara,
please don’t worry, all our work is for free and you can of course use it commercially. We appreciate the link back, but what is more important is the license for the images which is Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0) which does not allow a commercial use. So you might be required to change the images that you are using for the slider.
@Hi, thank you for your concern, but there is really no problem that somebody uses our things – we do them so that they can be used without worrying about a license. What we wouldn’t like to see is if somebody would only take the components and sell them, as they are, without integrating them somehow. We’ve had cases like that and we don’t like it for one reason: People that buy it waste their money on something that is for free, and that, in my opinion is pretty mean.
Thanks again to both of you,
cheers,
ML
thank you so much. I’ll replace images in the slider, thanks.
I really love your works, and some times ago i sent a message using the contact form in this site asking the price for a custom slider, but i still wait a reply 🙂
(However, i don’t sell the images, i use the photos only in our live preview!)
This must be the best jQuery image slider I’ve ever seen. It is a shame that it doesn’t work in Google Chrome (12.0.742.122).
In Chrome – disable AdBlock, and reload it works…
something triggers it… (both here and Suerte’s theme as well)
Demo is working bad on Firefox. First and last images shown on outside of their areas for a while when on amination.
Hi Vedia,
which version of Firefox are you talking about? Thanks, cheers, ML
Is there anyway to make the slider much smaller and only feature 2 items? Can each of those items click through to different links?
Are there Ads being used on there ? Why would it work if I disable AdBlock !
Another great effect Mary Lou!
Did anyone find the solution for IE8?
That’s a great slide show you have. However, Firefox could not detects the position of the data-rotation. Causing problem for me to use this layout.
It allows me the first set of 4 images to rotate and none would appear next. 🙁
is there any way to stop auto “startSlideshow();” after 1st loop?
Hey Mary Lou,
First of all.. :
Thank you VERY much for all of these nice examples!
I would like to use part of this script to make a little (products-)banner.
Unfortunately, I do not seem to be able to put a (external) link to the pictures, div’s or ..anything for that matter. And since they rotate it is not an option to put a floating div on top..
I also saw that others where also not able to do so..
(Alex, Mark, Luca, Tabitha and Me)
Could you please help us/me out?
(using Safari)
Many thanks so far!
I was loading the demo in IE8, is it suppose to not curve and rotate like FireFox and Chrome?
it just slides and fades… is it by design to do that?
Nice slider! Thanks for the share!
It’s funny, I had a client come to me earlier today and ask me to create a slideshow in this exact fashion for them using jquery. I was devising a plan to write the code, and while taking a break, I stumbled upon this article. Exactly what I needed. Thank you 100 times!
Hi..This is amzing..I think of using it in one of my websites. But my website has a background image. Si in this situation how will I use this.
That’s good !
Thanks alot 🙂
Great work as always Mary Lou!
But Is there anyway to make the slider much smaller ?
Many thanks 🙂
Like many others on here, I’d like to be able to link the images and/or place a caption/tooltip on them. Has anyone found a solution to this yet?