From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
You have for sure already seen impress.js, a really great JavaScript library for creating extraordinary 3D presentations. The jQuery port jmpress.js let’s you use this library as a jQuery plugin with some added options. We want to show you today how to use this great plugin to create a responsive slideshow with 3D effects.
The icons used in the demo is by Artcore Illustration and they are licensed under the
Creative Commons BY-NC-ND 3.0 license.
So, let’s start!
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
We will have a main container which is a section with the class jms-slideshow. Inside, we’ll have sevaral divisions with the class step. These will be our single slides. Each step or slide will get a data-color class for it’s background color and some data attributes of jmpress.js. You can find all (inline) options here: jmpress.js Documentation – Options. We’ll use some attributes in order to define the position and rotation of the slides in 3D space:
<section id="jms-slideshow" class="jms-slideshow"> <div class="step" data-color="color-1"> <div class="jms-content"> <h3>Some headline</h3> <p>Some text</p> <a class="jms-link" href="#">Read more</a> </div> <img src="images/1.png" /> </div> <div class="step" data-color="color-2" data-y="500" data-scale="0.4" data-rotate-x="30"> <!-- ... --> </div> <!-- ... --> </section>
Let’s take care of the style.
The CSS
Since we want to make the slideshow responsive, we will give the main container a percentage width, with some min and max values:
.jms-slideshow { position: relative; width: 80%; max-width: 1400px; min-width: 640px; margin: 20px auto; height: 460px; }
The next wrapper is dynamically added, and this will be the visible slideshow wrapper:
.jms-wrapper { width: auto; min-width: 600px; height: 440px; background-color: #fff; box-shadow: 0 2px 6px rgba(0, 0, 0, .2); -webkit-background-clip: padding; -moz-background-clip: padding; background-clip: padding-box; border: 10px solid #fff; border: 10px solid rgba(255, 255, 255, 0.9); outline: none; transition: background-color 1s linear; }
The background color classes will be applied to the previous wrapper. The class is defined in the data atrribute data-color in each step. This gives us the possibility to add a background color for each slide and change it with a transition. (The duration of the transition will be re-defined in the JavaScript.)
.color-1 { background-color: #E3D8FF; background-color: rgba(227, 216, 268, 1); } .color-2 { background-color: #EBBBBC; background-color: rgba(235, 187, 188, 1); } .color-3 { background-color: #EED9C0; background-color: rgba(238, 217, 192, 1); } .color-4 { background-color: #DFEBB1; background-color: rgba(223, 235, 177, 1); } .color-5{ background-color: #C1E6E5; background-color: rgba(193, 230, 229, 1); }
The steps will have the following style:
.step { width: 900px; height: 420px; display: block; transition: opacity 1s; } .step:not(.active) { opacity: 0; }
Inactive steps will have 0 opacity. When the slides are moved, the opacity will be set to 1.
The inner parts of the slides will have the following style:
.jms-content{ margin: 0px 370px 0px 20px; position: relative; clear: both; } .step h3{ color: #fff; font-size: 52px; font-weight: bold; text-shadow: 1px 1px 1px rgba(0,0,0,0.1); margin: 0; padding: 60px 0 10px 0; } .step p { color: #fff; text-shadow: 1px 1px 1px rgba(0,0,0,0.1); font-size: 34px; font-weight: normal; position: relative; margin: 0; }
The “read more” link will have a little transition by itself: once a step becomes active, it will move up wile fading in:
a.jms-link{ color: #fff; text-transform: uppercase; background: linear-gradient(top, #969696 0%,#727272 100%); padding: 8px 15px; display: inline-block; font-size: 16px; font-weight: bold; color: #fff; text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5); border: 1px solid #444; border-radius: 4px; opacity: 1; margin-top: 40px; clear: both; transition: all 0.4s ease-in-out 1s; } .step:not(.active) a.jms-link{ opacity: 0; margin-top: 80px; }
The image will be positioned absolutely on the right side of each slide:
.step img{ position: absolute; right: 0px; top: 30px; }
The navigation dots will positioned at the bottom:
.jms-dots{ width: 100%; position: absolute; text-align: center; left: 0px; bottom: 20px; z-index: 2000; user-select: none; }
With “user-select: none” the text of an element and its sub-elements will appear as if they can’t be selected.
The span will be a dark little dot:
.jms-dots span{ display: inline-block; position: relative; width: 12px; height: 12px; border-radius: 50%; background: #777; margin: 3px; cursor: pointer; box-shadow: 1px 1px 1px rgba(0,0,0,0.1) inset, 1px 1px 1px rgba(255,255,255,0.3); }
And we’ll style a pseudo-element to look like a little white dot:
.jms-dots span.jms-dots-current:after{ content: ''; width: 8px; height: 8px; position: absolute; top: 2px; left: 2px; border-radius: 50%; background: linear-gradient(top, #ffffff 0%,#f6f6f6 47%,#ededed 100%); }
The arrow navigation spans will be positioned on the left and on the right side of the slideshow. We’ll use background images for the arrows:
.jms-arrows{ user-select: none; } .jms-arrows span{ position: absolute; top: 50%; margin-top: -40px; height: 80px; width: 30px; cursor: pointer; z-index: 2000; box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.1); border-radius: 3px; } .jms-arrows span.jms-arrows-prev{ background: #fff url(../images/arrow_left.png) no-repeat 50% 50%; left: -10px; } .jms-arrows span.jms-arrows-next{ background: #fff url(../images/arrow_right.png) no-repeat 50% 50%; right: -10px; }
Now we have styled the slideshow. Let’s move on to the JavaScript!
The JavaScript
We will be using the jmpress.js plugin to create our slideshow. Although you can make use of a lot of its functionality, we will just use the necessary parts to build our script. You can read more about the possibilities and options that jmpress.js offers here.
We will create a jQuery plugin for the slideshow. We can call the plugin like this:
$( '#jms-slider' ).jmslideshow();
The options for the jmpress plugin are defined as default options in our plugin (note that you can specify more than the ones listed):
jmpressOpts : { // set the viewport viewPort : { height : 400, width : 1300, maxScale: 1 }, fullscreen : false, hash : { use : false }, mouse : { clickSelects : false }, keyboard : { use : false }, animation : { transitionDuration : '1s' } },
You can either change them inside the slideshow plugin, or pass a specific value when you initialize the plugin. As an example:
// specify the jmpress options var jmpressOpts = { animation : { transitionDuration : '0.8s' } }; // call the jmslideshow plugin $( '#jms-slideshow' ).jmslideshow( $.extend( true, { jmpressOpts : jmpressOpts }, { autoplay : true, bgColorSpeed: '0.8s', arrows : false }));
The following are the set of available options that are available for the slideshow plugin:
$.JMSlideshow.defaults = { // options for the jmpress plugin. // you can add more options... jmpressOpts : { // set the viewport viewPort : { height : 400, width : 1300, maxScale: 1 }, fullscreen : false, hash : { use : false }, mouse : { clickSelects : false }, keyboard : { use : false }, animation : { transitionDuration : '1s' } }, // for this specific plugin we will have the following options: // shows/hides navigation arrows arrows : true, // shows/hides navigation dots/pages dots : true, // each step's bgcolor transition speed bgColorSpeed: '1s', // slideshow on / off autoplay : false, // time between transitions for the slideshow interval : 3500 };
Once the slideshow plugin is called, the first function to be executed is the init function:
_init : function( options ) { this.options = $.extend( true, {}, $.JMSlideshow.defaults, options ); // the slides this.$slides = $('#jms-slider').children('div'); // total number of slides this.slidesCount = this.$slides.length; // step's bgcolor this.colors = $.map( this.$slides, function( el, i ) { return $( el ).data( 'color' ); } ).join( ' ' ); // build the necessary structure to run jmpress this._layout(); // initialize the jmpress plugin this._initImpress(); // if support (function implemented in jmpress plugin) if( this.support ) { // load some events this._loadEvents(); // if autoplay is true start the slideshow if( this.options.autoplay ) { this._startSlideshow(); } } },
In the _layout function we are building the necessary structure for the jmpress plugin. Also, we will be adding the navigation arrows / dots in case these are set to true in the options.
_layout : function() { // adds a specific class to each one of the steps this.$slides.each( function( i ) { $(this).addClass( 'jmstep' + ( i + 1 ) ); } ); // wrap the slides. This wrapper will be the element on which we will call the jmpress plugin this.$jmsWrapper = this.$slides.wrapAll( '<div class="jms-wrapper"/>' ).parent(); // transition speed for the wrapper bgcolor this.$jmsWrapper.css( { '-webkit-transition-duration' : this.options.bgColorSpeed, '-moz-transition-duration' : this.options.bgColorSpeed, '-ms-transition-duration' : this.options.bgColorSpeed, '-o-transition-duration' : this.options.bgColorSpeed, 'transition-duration' : this.options.bgColorSpeed } ); // add navigation arrows if( this.options.arrows ) { this.$arrows = $( '<nav class="jms-arrows"/>' ); if( this.slidesCount > 1 ) { this.$arrowPrev = $( '<span class="jms-arrows-prev"/>' ).appendTo( this.$arrows ); this.$arrowNext = $( '<span class="jms-arrows-next"/>' ).appendTo( this.$arrows ); } this.$el.append( this.$arrows ) } // add navigation dots if( this.options.dots ) { this.$dots = $( '<nav class="jms-dots"/>' ); for( var i = this.slidesCount + 1; --i; ) { this.$dots.append( ( i === this.slidesCount ) ? '<span class="jms-dots-current"/>' : '<span/>' ); } if( this.options.jmpressOpts.start ) { this.$start = this.$jmsWrapper.find( this.options.jmpressOpts.start ), idxSelected = 0; ( this.$start.length ) ? idxSelected = this.$start.index() : this.options.jmpressOpts.start = null; this.$dots.children().removeClass( 'jms-dots-current' ).eq( idxSelected ).addClass( 'jms-dots-current' ); } this.$el.append( this.$dots ) } },
We will initialize the jmpress plugin in the _initImpress function. We will also redefine the “setActive” method of jmpress in order to switch the active navigation dot.
_initImpress : function() { var _self = this; this.$jmsWrapper.jmpress( this.options.jmpressOpts ); // check if supported (function from jmpress.js): // it adds the class not-suported to the wrapper this.support = !this.$jmsWrapper.hasClass( 'not-supported' ); // if not supported remove unnecessary elements if( !this.support ) { if( this.$arrows ) { this.$arrows.remove(); } if( this.$dots ) { this.$dots.remove(); } return false; } // redefine the jmpress setActive method this.$jmsWrapper.jmpress( 'setActive', function( slide, eventData ) { // change the pagination dot active class if( _self.options.dots ) { // adds the current class to the current dot/page _self.$dots .children() .removeClass( 'jms-dots-current' ) .eq( slide.index() ) .addClass( 'jms-dots-current' ); } // delete all current bg colors this.removeClass( _self.colors ); // add bg color class this.addClass( slide.data( 'color' ) ); } ); // add step's bg color to the wrapper this.$jmsWrapper.addClass( this.$jmsWrapper.jmpress('active').data( 'color' ) ); },
The _startSlideshow and _stopSlideshow will start and stop the slideshow respectively if the option autoplay is set to true.
// start slideshow if autoplay is true _startSlideshow : function() { var _self = this; this.slideshow = setTimeout( function() { _self.$jmsWrapper.jmpress( 'next' ); if( _self.options.autoplay ) { _self._startSlideshow(); } }, this.options.interval ); }, // stops the slideshow _stopSlideshow : function() { if( this.options.autoplay ) { clearTimeout( this.slideshow ); this.options.autoplay = false; } },
Finally, we load the events for the navigation arrows and dots. The touchend event is already defined in the jmpress plugin, but we will need to stop the slideshow in case this event is triggered:
_loadEvents : function() { var _self = this; // navigation arrows if( this.$arrowPrev && this.$arrowNext ) { this.$arrowPrev.on( 'click.jmslideshow', function( event ) { _self._stopSlideshow(); _self.$jmsWrapper.jmpress( 'prev' ); return false; } ); this.$arrowNext.on( 'click.jmslideshow', function( event ) { _self._stopSlideshow(); _self.$jmsWrapper.jmpress( 'next' ); return false; } ); } // navigation dots if( this.$dots ) { this.$dots.children().on( 'click.jmslideshow', function( event ) { _self._stopSlideshow(); _self.$jmsWrapper.jmpress( 'goTo', '.jmstep' + ( $(this).index() + 1 ) ); return false; } ); } // the touchend event is already defined in the jmpress plugin. // we just need to make sure the slideshow stops if the event is triggered this.$jmsWrapper.on( 'touchend.jmslideshow', function() { _self._stopSlideshow(); } ); }
And that’s it! I hope you enjoyed this tutorial and find it useful!
USEFUL!!!
WoW, it’s great. Thank you.
I am afraid it is not supported by most of the browsers. At least the just couple of browsers support it with 3D transition.
Thanks for your feedback. How do you mean “most” π ? It works in Safari, Firefox, Chrome and Opera. That sounds like a solid majority to me π
Cheers, ML
Has anyone tested this with IE7 ??
Works in IE7, IE8 and IE9 – of course not with the same effects, but the slider can be used with the Internet Explorer too.
Good job, Mary Lou!
I get a display error in autoplay – second and last slide (chrome). Still its cool.
Hey there Mary, this one’s another fabulous tutorial. But I gotta query. Will it work in systems that can’t support this level of high transitions? Is it feasible to use it in live projects?
Ask yourself: will the old browser user miss important information if I use this effect ? Or is it just that the site will be less pretty (but pretty enough) for him ?
If you’re in the latest case, go on and use the effect (impress.js, css transitions, css animations, …) !
fantastic mam :), i don’t know who’s inspiring you for make this project..
and thanks if u want answer my question, Can i know what do u think about web design in Indonesia?
Very great effect and I love the way you explained how everything works and why. As usual, amazing and useful!
I wonder how it would work with a full image instead of text and icons?
WOW you always awesome, I love you Merry Lou :* muach muach muach π
Thanks a ton Mary.. you always come up with good stuff..will definitely use this in my future wok..
Lovely plugin, and thanks for the explanation. Keep it up!
Wow! I’m completely impressed. An amazing use of jmpress.js! I wish our demo looked that good. : ) Nice work!
wonderful
can anyone give a good list level of browsers that support it also
do we need html 5 polyfills?
bo
Can you make a tutorial with image thumbnails slider with the same great effects, please?
This is sexy… Thanks Mary Lou!
Nice show
I had just a little concern about the html5 markup: You have one containing multiple . Semantically, I think it would have been better to have one containing multiple .
Sorry I forgot I can’t use tags π . Let’s write it again:
Nice show
I had just a little concern about the html5 markup: You have one section containing multiple divs. Semantically, I think it would have been better to have one div containing multiple sections.
I think, one Section + multi-divs with figure/figcaption inside is best semantic:
– Section = Region of the Slider
– div = wrapper without semantic, only for layout
– figure = the SingleSlide with img inside
– figcaption = The “wrapper” for the headline, text, links…
What do you think??
just One word…. AWESOME!!!
You’re just a great source of Inspiration Mary Lou…. (I don’t know if it’s correct… I’m french… lol)
Thank you for all of your Work!! π
It’s a really impress ive :d
Nice-looking example! Also gives me some good ideas for Presenteer.js, a similar tool..!
Nice work. What about the license?
Thanks. License: http://tympanus.net/codrops/licensing/
Awesome. thank you so much mary :X
Very nice slider, thanks a lot
Awesome slider!!!! Tnx and respect from Russia
Beautiful Mary. Thanks a bunch for posting this! π
Its not working in IE 9, Can i have any solution to fix it out?
I tried everything, but did not work! Can anyone help me?
Respect – from Malaysia! Thanks so much!
Great work awesome !!!!! thanks
Excellent, loved it. Thanks for sharing.
Hi Mary- Its awesome! Can you give me a solution to work this in IE ?
And now we need a WordPress Plugin like this π
Anyone who says “Challenge accepted! I will do it?” ?
This is awesome. Your sites generally are the best source for inspiration. Thanks
Hi Mary Lou
This is a really nice jquery slider, I particularly like the fact that it uses real text as apposed to block images. The transitional effects are nice too although I think I would stick to just one effect, to avoid over complicating things or confusing a user.
Cathy
Brilliant! Thanks for the tutorial.
Great! Will use it on my next project
Awesome! Thanks, will use it for my next project.
hi i tried you demo, But i found that the last slide is not visible completely.
Breathtaking. Can’t wait to get my devs started on this one. Thanks Mary.
Brilliant,
The slide effects are awesome…better than the fade in and slide effects. Excellent work!!
Mary Lou is the best web designer… Very good work
Nice Script, Like the Transitional effect, surely gona use it soon, thanks. Keep up the goOd work guyz….
I tried this on my iPhone. This isn’t responsive, wtf?
I have the same problem. Maybe some orientation to resolve? I could share the solution. Thx!
Cool Thanks!!!
Very nice job! It would be even better if it supported smartphones too.
Hi miss mary lou ..
sorry I strayed from the topic, may I ask scrip like other post on Slide Down Menu with jQuery Box and CSS3 .. please
Hello Mary, it’s really nice! And i notice this works well in the browser i am using now (Firefox 9.0.1) while the official demo (http://bartaz.github.com/impress.js/) doesn’t (it already states that it works best on Firefox 10 but then, yours’ working fine!) and i’ve been wondering.. What makes your code work? Would you mind pointing out the key point? I am just starting with impress.js and this code seems to be more complicated than the official demo, so i want to make the official demo works in my browser. Thank you π
Hi Juni, I am actually using the jmpress jQuery plugin, not the impress.js script. I am not sure if I can point you out the difference between both concerning the impress.js functionality. Anyway, as far as I saw on https://github.com/bartaz/impress.js/, impress.js is just working “fine” in firefox >= 10 :S Cheers, ML
Sorry my reply is so slow. Ah i see. Thank you so much Mary, good luck π
Man I just love the transitions on this slider… great job Mary !
Hi! Loved this plugin, thanks Mary! Got one newbie question, how can i add stop after cycle option? thanks people!)
Can’t get it to switch between slides in IE8. Anyone with the same problem? Something obvious that I’ve missed?
More info: Looks like the classes .loaded and .active doesn’t trigger on other than the first slide.