Full Width Image Slider

A very simple 100% width slider that scales down to mobile.
Full Width Image Slider

From our monthly sponsor: Ship customer-facing metrics fast with Keen.io. Collect, store, query, & display stunning analytics.

This slider has a 100% width layout and it is responsive. It operates with CSS transitions and the image is wrapped with an anchor. The anchor can be replaced by a division if no linking is needed. With a max-width set to 100%, the image will size down for smaller screens.

The HTML

<div id="cbp-fwslider" class="cbp-fwslider">
	<ul>
		<li><a href="#"><img src="images/1.jpg" alt="img01"/></a></li>
		<li><a href="#"><img src="images/2.jpg" alt="img02"/></a></li>
		<li><a href="#"><img src="images/3.jpg" alt="img03"/></a></li>
		<li><a href="#"><img src="images/4.jpg" alt="img04"/></a></li>
		<li><a href="#"><img src="images/5.jpg" alt="img05"/></a></li>
	</ul>
</div>

The CSS

.cbp-fwslider {
	position: relative;
	margin: 0 0 10px;
	overflow: hidden;
	padding: 40px 0 60px;
}

.cbp-fwslider ul {
	margin: 0;
	padding: 0;
	white-space: nowrap;
	list-style-type: none;
}

.cbp-fwslider ul li {
	transform: translateZ(0);
	float: left;
	display: block;
	margin: 0;
	padding: 0;
}

.cbp-fwslider ul li > a,
.cbp-fwslider ul li > div {
	display: block;
	text-align: center;
	outline: none;
}

.cbp-fwslider ul li > a img {
	border: none;
	display: block;
	margin: 0 auto;
	max-width: 75%;
}

.cbp-fwslider nav span {
	position: absolute;
	top: 50%;
	width: 50px;
	height: 100px;
	background: #47a3da;
	color: #fff;
	font-size: 50px;
	text-align: center;
	margin-top: -50px;
	line-height: 100px;
	cursor: pointer;
	font-weight: normal;
}

.cbp-fwslider nav span:hover {
	background: #378fc3;
}

.cbp-fwslider nav span.cbp-fwnext {
	right: 0px;
}

.cbp-fwslider nav span.cbp-fwprev {
	left: 0px;
}

.cbp-fwdots {
	position: absolute;
	bottom: 0px;
	white-space: nowrap;
	text-align: center;
	width: 100%;
}

.cbp-fwdots span {
	display: inline-block;
	width: 18px;
	height: 18px;
	background: #ddd;
	margin: 4px;
	border-radius: 50%;
	cursor: pointer;
}

.cbp-fwdots span:hover {
	background: #999;
}

.cbp-fwdots span.cbp-fwcurrent {
	background: #47a3da;
	box-shadow: 0 0 0 2px #47a3da;
	transition: box-shadow 0.2s ease-in-out;
}

The JavaScript

;( function( $, window, undefined ) {

	'use strict';

	// global
	var Modernizr = window.Modernizr;

	$.CBPFWSlider = function( options, element ) {
		this.$el = $( element );
		this._init( options );
	};

	// the options
	$.CBPFWSlider.defaults = {
		// default transition speed (ms)
		speed : 500,
		// default transition easing
		easing : 'ease'
	};

	$.CBPFWSlider.prototype = {
		_init : function( options ) {
			// options
			this.options = $.extend( true, {}, $.CBPFWSlider.defaults, options );
			// cache some elements and initialize some variables
			this._config();
			// initialize/bind the events
			this._initEvents();
		},
		_config : function() {

			// the list of items
			this.$list = this.$el.children( 'ul' );
			// the items (li elements)
			this.$items = this.$list.children( 'li' );
			// total number of items
			this.itemsCount = this.$items.length;
			// support for CSS Transitions & transforms
			this.support = Modernizr.csstransitions && Modernizr.csstransforms;
			this.support3d = Modernizr.csstransforms3d;
			// transition end event name and transform name
			var transProperties = {
				'WebkitTransition' : { transitionEndEvent : 'webkitTransitionEnd', tranformName : '-webkit-transform' },
				'MozTransition' : { transitionEndEvent : 'transitionend', tranformName : '-moz-transform' },
				'OTransition' : { transitionEndEvent : 'oTransitionEnd', tranformName : '-o-transform' },
				'msTransition' : { transitionEndEvent : 'MSTransitionEnd', tranformName : '-ms-transform' },
				'transition' : { transitionEndEvent : 'transitionend', tranformName : 'transform' }
			};
			if( this.support ) {
				this.transEndEventName = transProperties[ Modernizr.prefixed( 'transition' ) ].transitionEndEvent + '.cbpFWSlider';
				this.transformName = transProperties[ Modernizr.prefixed( 'transition' ) ].tranformName;
			}
			// current and old item´s index
			this.current = 0;
			this.old = 0;
			// check if the list is currently moving
			this.isAnimating = false;
			// the list (ul) will have a width of 100% x itemsCount
			this.$list.css( 'width', 100 * this.itemsCount + '%' );
			// apply the transition
			if( this.support ) {
				this.$list.css( 'transition', this.transformName + ' ' + this.options.speed + 'ms ' + this.options.easing );
			}
			// each item will have a width of 100 / itemsCount
			this.$items.css( 'width', 100 / this.itemsCount + '%' );
			// add navigation arrows and the navigation dots if there is more than 1 item
			if( this.itemsCount > 1 ) {

				// add navigation arrows (the previous arrow is not shown initially):
				this.$navPrev = $( '<span class="cbp-fwprev"><</span>' ).hide();
				this.$navNext = $( '<span class="cbp-fwnext">></span>' );
				$( '<nav/>' ).append( this.$navPrev, this.$navNext ).appendTo( this.$el );
				// add navigation dots
				var dots = '';
				for( var i = 0; i < this.itemsCount; ++i ) {
					// current dot will have the class cbp-fwcurrent
					var dot = i === this.current ? '<span class="cbp-fwcurrent"></span>' : '<span></span>';
					dots += dot;
				}
				var navDots = $( '<div class="cbp-fwdots"/>' ).append( dots ).appendTo( this.$el );
				this.$navDots = navDots.children( 'span' );

			}

		},
		_initEvents : function() {
			
			var self = this;
			if( this.itemsCount > 1 ) {
				this.$navPrev.on( 'click.cbpFWSlider', $.proxy( this._navigate, this, 'previous' ) );
				this.$navNext.on( 'click.cbpFWSlider', $.proxy( this._navigate, this, 'next' ) );
				this.$navDots.on( 'click.cbpFWSlider', function() { self._jump( $( this ).index() ); } );
			}

		},
		_navigate : function( direction ) {

			// do nothing if the list is currently moving
			if( this.isAnimating ) {
				return false;
			}

			this.isAnimating = true;
			// update old and current values
			this.old = this.current;
			if( direction === 'next' && this.current < this.itemsCount - 1 ) {
				++this.current;
			}
			else if( direction === 'previous' && this.current > 0 ) {
				--this.current;
			}
			// slide
			this._slide();

		},
		_slide : function() {

			// check which navigation arrows should be shown
			this._toggleNavControls();
			// translate value
			var translateVal = -1 * this.current * 100 / this.itemsCount;
			if( this.support ) {
				this.$list.css( 'transform', this.support3d ? 'translate3d(' + translateVal + '%,0,0)' : 'translate(' + translateVal + '%)' );
			}
			else {
				this.$list.css( 'margin-left', -1 * this.current * 100 + '%' );	
			}
			
			var transitionendfn = $.proxy( function() {
				this.isAnimating = false;
			}, this );

			if( this.support ) {
				this.$list.on( this.transEndEventName, $.proxy( transitionendfn, this ) );
			}
			else {
				transitionendfn.call();
			}

		},
		_toggleNavControls : function() {

			// if the current item is the first one in the list, the left arrow is not shown
			// if the current item is the last one in the list, the right arrow is not shown
			switch( this.current ) {
				case 0 : this.$navNext.show(); this.$navPrev.hide(); break;
				case this.itemsCount - 1 : this.$navNext.hide(); this.$navPrev.show(); break;
				default : this.$navNext.show(); this.$navPrev.show(); break;
			}
			// highlight navigation dot
			this.$navDots.eq( this.old ).removeClass( 'cbp-fwcurrent' ).end().eq( this.current ).addClass( 'cbp-fwcurrent' );

		},
		_jump : function( position ) {

			// do nothing if clicking on the current dot, or if the list is currently moving
			if( position === this.current || this.isAnimating ) {
				return false;
			}
			this.isAnimating = true;
			// update old and current values
			this.old = this.current;
			this.current = position;
			// slide
			this._slide();

		},
		destroy : function() {

			if( this.itemsCount > 1 ) {
				this.$navPrev.parent().remove();
				this.$navDots.parent().remove();
			}
			this.$list.css( 'width', 'auto' );
			if( this.support ) {
				this.$list.css( 'transition', 'none' );
			}
			this.$items.css( 'width', 'auto' );

		}
	};

	var logError = function( message ) {
		if ( window.console ) {
			window.console.error( message );
		}
	};

	$.fn.cbpFWSlider = function( options ) {
		if ( typeof options === 'string' ) {
			var args = Array.prototype.slice.call( arguments, 1 );
			this.each(function() {
				var instance = $.data( this, 'cbpFWSlider' );
				if ( !instance ) {
					logError( "cannot call methods on cbpFWSlider prior to initialization; " +
					"attempted to call method '" + options + "'" );
					return;
				}
				if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
					logError( "no such method '" + options + "' for cbpFWSlider instance" );
					return;
				}
				instance[ options ].apply( instance, args );
			});
		} 
		else {
			this.each(function() {	
				var instance = $.data( this, 'cbpFWSlider' );
				if ( instance ) {
					instance._init();
				}
				else {
					instance = $.data( this, 'cbpFWSlider', new $.CBPFWSlider( options, this ) );
				}
			});
		}
		return this;
	};

} )( jQuery, window );

Tagged with:

ML is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

http://www.codrops.com

Receive our bi-weekly Collective or official newsletter right in your inbox.

CSS Reference

Learn about all important CSS properties from the basics with our extensive and easy-to-read CSS Reference.

It doesn't matter if you are a beginner or intermediate, start learning CSS now.

Feedback 147

Comments are closed.
  1. and of course,
    if you want it to be start over when it is finished
    update those function like that…

    autoplay : function(){
    if((this.current) == (this.itemsCount-1)){
    this.current = -1;
    }
    else{
    this._navigate(‘next’);
    }
    },

    interval : function(){
    var that = this;
    setInterval(function(){
    return that.autoplay();
    },5000);
    }

    cheers

    • Thank you for this code.
      It runs perfectly.
      The only thing I had to change is the line “this._navigate(‘next’);” replaced by “this._navigate(‘next’);”
      Can’t see the difference ?
      It’s on this character : ‘ (on both sides of the word “next”)

  2. Love this slider, thanks! I’ve changed a bit of CSS to load each slide 100% of the page (without the white space in between) and I’ve set a min-height to 250px so the slides don’t get ridiculously thin on small screens. One thing I can’t seem to figure out though is how to center the image on the screen so that the left and right sides are cut off once the slide has met its define minimum height. By default it loads the left side of the image so that the whole right side is cut off… does anyone know how to center it? As a point of reference, check out squarespace.com ‘s header graphic.

    • Hi!
      May I ask what you have changed to get rid of the white space on both sides of the image?
      Thanks!!

  3. Hi!

    I have a question regarding the autoplay code that was posted above. Exactly where am I going to implement that pice of code?
    Can you give me an example?

    Many thanx

    / Adam

    • Hi Adam,
      put this above code, to the jquery.cbpFWSlider.js first prototype function,
      and call this method when you implement cbpFWSlider in your js,
      like that :

      $( ‘#cbp-fwslider’ ).cbpFWSlider();
      $( ‘#cbp-fwslider’ ).cbpFWSlider(‘interval’);

  4. Hi!

    Thank you for your replay!
    I am new to jquery so I have trouble implementing the code in the jquery.cbpFWSlider.min.js. The method is no problem.

    My jquery.cbpFWSlider.min.js looks like this:

    (function(c,b,e){var d=b.Modernizr;c.CBPFWSlider=function(f,g){this.$el=c(g);this._init(f)};c.CBPFWSlider.defaults={speed:500,easing:”ease”};c.CBPFWSlider.prototype={_init:function(f){this.options=c.extend(true,{},c.CBPFWSlider.defaults,f);this._config();this._initEvents()},_config:function(){this.$list=this.$el.children(“ul”);this.$items=this.$list.children(“li”);this.itemsCount=this.$items.length;this.support=d.csstransitions&&d.csstransforms;this.support3d=d.csstransforms3d;var h={WebkitTransition:”webkitTransitionEnd”,MozTransition:”transitionend”,OTransition:”oTransitionEnd”,msTransition:”MSTransitionEnd”,transition:”transitionend”},k={WebkitTransform:”-webkit-transform”,MozTransform:”-moz-transform”,OTransform:”-o-transform”,msTransform:”-ms-transform”,transform:”transform”};if(this.support){this.transEndEventName=h[d.prefixed(“transition”)]+”.cbpFWSlider”;this.transformName=k[d.prefixed(“transform”)]}this.current=0;this.old=0;this.isAnimating=false;this.$list.css(“width”,100*this.itemsCount+”%”);if(this.support){this.$list.css(“transition”,this.transformName+” “+this.options.speed+”ms “+this.options.easing)}this.$items.css(“width”,100/this.itemsCount+”%”);if(this.itemsCount>1){this.$navPrev=c(‘<‘).hide();this.$navNext=c(‘>’);c(“”).append(this.$navPrev,this.$navNext).appendTo(this.$el);var l=””;for(var g=0;g<this.itemsCount;++g){var f=g===this.current?'’:””;l+=f}var j=c(”).append(l).appendTo(this.$el);this.$navDots=j.children(“span”)}},_initEvents:function(){var f=this;if(this.itemsCount>1){this.$navPrev.on(“click.cbpFWSlider”,c.proxy(this._navigate,this,”previous”));this.$navNext.on(“click.cbpFWSlider”,c.proxy(this._navigate,this,”next”));this.$navDots.on(“click.cbpFWSlider”,function(){f._jump(c(this).index())})}},_navigate:function(f){if(this.isAnimating){return false}this.isAnimating=true;this.old=this.current;if(f===”next”&&this.current0){–this.current}}this._slide()},_slide:function(){this._toggleNavControls();var g=-1*this.current*100/this.itemsCount;if(this.support){this.$list.css(“transform”,this.support3d?”translate3d(“+g+”%,0,0)”:”translate(“+g+”%)”)}else{this.$list.css(“margin-left”,-1*this.current*100+”%”)}var f=c.proxy(function(){this.isAnimating=false},this);if(this.support){this.$list.on(this.transEndEventName,c.proxy(f,this))}else{f.call()}},_toggleNavControls:function(){switch(this.current){case 0:this.$navNext.show();this.$navPrev.hide();break;case this.itemsCount-1:this.$navNext.hide();this.$navPrev.show();break;default:this.$navNext.show();this.$navPrev.show();break}this.$navDots.eq(this.old).removeClass(“cbp-fwcurrent”).end().eq(this.current).addClass(“cbp-fwcurrent”)},_jump:function(f){if(f===this.current||this.isAnimating){return false}this.isAnimating=true;this.old=this.current;this.current=f;this._slide()},destroy:function(){if(this.itemsCount>1){this.$navPrev.parent().remove();this.$navDots.parent().remove()}this.$list.css(“width”,”auto”);if(this.support){this.$list.css(“transition”,”none”)}this.$items.css(“width”,”auto”)}};var a=function(f){if(b.console){b.console.error(f)}};c.fn.cbpFWSlider=function(g){if(typeof g===”string”){var f=Array.prototype.slice.call(arguments,1);this.each(function(){var h=c.data(this,”cbpFWSlider”);if(!h){a(“cannot call methods on cbpFWSlider prior to initialization; attempted to call method ‘”+g+”‘”);return}if(!c.isFunction(h[g])||g.charAt(0)===”_”){a(“no such method ‘”+g+”‘ for cbpFWSlider instance”);return}h[g].apply(h,f)})}else{this.each(function(){var h=c.data(this,”cbpFWSlider”);if(h){h._init()}else{h=c.data(this,”cbpFWSlider”,new c.CBPFWSlider(g,this))}})}return this}})(jQuery,window);

    I would be greateful if I could get some further help.
    Thanx again!

  5. Hey.

    I took this slider to use on my website but the transition did not occur with an animation. The picture just jumps to the next. I tested it on both firefox and chrome.. I didnt change anything just added the css and the javascript which I downloaded and added some images.

    <a href=”#” rel=”nofollow”><img src="images/labs/Innovations.jpg” alt=”img01″/></a>
    <a href=”#” rel=”nofollow”><img src="images/labs/Digital Insight.jpg” alt=”img02″/></a>
    <a href=”#” rel=”nofollow”><img src="images/labs/Innovations.jpg” alt=”img03″/></a>

    Not sure what might be going wrong here. Any help will be appreciated.

    Thanks in advance.
    Ad

    • I cant paste the code here it doesnt show up properly. But I use php to get the location of the image php echo $themeUrl and then select the image. I dont think this should be an issue but just thought Ill let you know in case it does affect the slider.

      Thank you.

    • I had the same issue. Originally I didn’t include modernizr.custom.js in my files. Once I added it back in, the images transitioned as expected.

  6. Hey,

    I am using the slider in one of my web sites but I dont get the transition effect when I change slides. I checked it on chrome and Firefox both but still not luck. Is it only me or does this problem exist for others as well ?

    I didnt change anything (css or javascript) just added some images using php to get the theme location and then navigate to the image. Is this a problem ?

    Thank you.
    Ad

  7. this is a good slideshow as i can place responsive layouts within its content. I have read through all the comments and discussions and i am struggling with pausing the slideshow on mouse hover/over. This is very important if i am to us this slider but none of the scripts seem to enable this function that are provided in the discussion. Could you please let me know if this option is available? Also I am struggling to add the cyclic option so the slides never end on clicks and you can go around as many times, with the next or prev button, as you wish without having to click back. Is this an option?

  8. Hi!
    Im using this script for a mobile preview of product list.
    I was wandering how can i tell the script at which slide i want it to open.
    I have a list of images, when you click on one of them slider opens.
    I want it to open on clicked one.
    In the script i found this.current and this.old, propably the ones that need to be set.
    Can anybody put me on the right direction?
    Jakub

  9. great slider! Any quick way to incorporate font awesome icons to replace the forward/back arrows?

  10. For the issue with the background not centering. The attribute for that was set up as an absolute in the javascript. you can over ride it in CSS styles

    div.JB_Slide div:first-child {
    background-repeat: no-repeat !important;
    background-position: center !important;
    }

    Wish I could take credit for figuring it out, rather simple for a developer, so I asked one. :0) Thought I would share.

  11. The centering of the images doesn’t seem to work. Has anyone another idea for that?

  12. Hi everybody! I need some autoplay for this code, that always works regardless of the mouse event. Is that possible? Just stop the autoplay if Iclick some of the navigation elements. And when I reach the last slide, go back to first. I’ll be very grateful for your help! Sorry for my poor English. 🙂

  13. Hi, Autoplay feature would make this AWESOME, one thing I did spot was that when you hovered over an area outside of the tablet you were still on a ‘#’ link..

  14. How do I make it auto slide, I sow some suggestions here but none of them worked. I need you to tell me exactly in which file it needs to be added.

    Thanks a lot of help!

  15. Here is how to make it autoplay using Özgür’s code.

    Put this right after CBPFWSlider.prototype = {

    autoplay : function(){
    if((this.current) == (this.itemsCount-1)){
    this.current = -1;
    }
    else{
    this._navigate('next');
    }
    },
    interval : function(){
    var that = this;
    setInterval(function(){
    return that.autoplay();
    },300);
    },

    Now the script before the closing body tag will now look like this:

    $( function() {
    $( '#cbp-fwslider' ).cbpFWSlider();
    $( '#cbp-fwslider' ).cbpFWSlider('interval');
    } );

    Thanks for everyone’s help! I love this slider.

  16. Hi!

    The auto play code above worked perfect! Thanx a lot!
    But I do have a question. When the last slide is showing the arrow to the right disappears and it is impossible to reach the first slide without going back the same way we come frome. Is it possible to make it “infinity”, so the right arrow wont disappear?

    Thanx alot

    /Adam

    • Hey.

      Seems like you got the slider to actually go back to the beginning after it finishes its first round.. Could you let me know how you did this ? 🙂 thanks heaps..