Finding a slideshow plugin for jQuery might seem like it’s going to be an easy task, but it takes time to review them, and there are a few things to consider. Since I’ve been working with responsive web design lately, a slideshow plugin’s ability to scale with the rest of the design is very important. There are other factors to consider though, and in the end I chose FlexSlider by WooThemes.
FlexSlider Isn’t Perfect
Part of a good responsive design is that it loads only minimal assets and mobile optimized images as part of a mobile-first design strategy. This means my slideshow needs different images at different screen widths, and I need to be able to change those images if the window is resized or the device orientation is changed.
Maybe I’m just a dummy, but Flexslider’s API was too hard to use for this simple task. I suppose the fact that there was very little in the way of documentation didn’t help, and I really didn’t want to have to browse code for hours on end just to figure out what was going on. I tried searching online, and found a lot of undocumented solutions on Stack Overflow, but these solutions were buggy, and window resize or orientation changes broke the slideshow on my iPad and my Android phone.
So Let’s Fix It Already!
In the latest version of FlexSlider there is an addSlide method and a removeSlide method, but adding and removing slides would either stop my slideshow, or there was a huge lag when loading the new slides. Again, this was totally broken on my Android phone and iPad. I went around in circles with this for a while, then stumbled up a real solution by Matt Wilcox. Yes, while this solution works, I could see some simple ways to improve on this, so here is what I changed:
- Matt suggests completely rebuilding and reinitializing the slideshow, but all that really needs to be done is to delete the slideshow element’s data object.
- Matt’s script constantly monitors the width of the screen, which isn’t necessary because we can just perform the necessary functions when the screen is resized, or when there is a device orientation change.
The HTML
<div class="slideshow mobile-slideshow"> <div class="flexslider"> <ul class="slides"> <li> <a href="/a"> <img src="/img/one-mobile.jpg" alt="img/link #1" /> </a> </li> <li> <a href="/b"> <img src="/img/two-mobile.jpg" alt="img/link #2" /> </a> </li> <li> <a href="/c"> <img src="/img/three-mobile.jpg" alt="img/link #3" /> </a> </li> <li> <a href="/d"> <img src="/img/four-mobile.jpg" alt="img/link #4" /> </a> </li> </ul> </div> </div>
The jQuery / JavaScript
(function($){ // Local Namespaced Functions var namespace = { /* Get the media query breakpoint number */ get_breakpoint: function(){ var color = $('#logo a').css('color'); var limit = 9; for( var i = 0; i <= limit; i++ ){ var rgb = 'rgb(' + i + ', ' + i + ', ' + i + ')'; if( color == rgb ){ return i; } } return limit; }, /** * Slideshow initialization */ slideshow_init: function(){ $('.flexslider').flexslider({ useCSS: false, animation: 'fade', directionNav: false }); }, /** * Set Slideshow image size */ set_slides: function(bp){ /* Determine the slide size for this breakpoint */ if(bp <= 1){ var slide_size = 'mobile'; }else{ var slide_size = ( bp <= 4 ) ? 'med' : 'std'; } /* If slide size matches slideshow class no reason to proceed */ if( ! $('.slideshow').hasClass( slide_size + '-slideshow' ) ){ /* Remove whatever slideshow size class there is */ $('.slideshow').removeClass('mobile-slideshow med-slideshow std-slideshow'); /* Add the new slideshow class */ $('.slideshow').addClass( slide_size + '-slideshow' ); var slides = '<li><a href="/a"><img src="/img/one-' + slide_size + '.jpg" /></a></li>' + '<li><a href="/b"><img src="/img/two-' + slide_size + '.jpg" /></a></li>' + '<li><a href="/c"><img src="/img/three-' + slide_size + '.jpg" /></a></li>' + '<li><a href="/d"><img src="/img/four-' + slide_size + '.jpg" /></a></li>'; /* Replace slides */ $('ul.slides').html( slides ); /** * If the slideshow had been previously initialized, * we need to remove the data and nav, then reinitialize */ if( $.hasData( $('.flexslider')[0] ) ){ $.removeData( $('.flexslider')[0] ); $('.flex-control-nav').remove(); funcs.slideshow_init(); } } } }; window.funcs = namespace; })(this.jQuery); // Document Ready Function $(document).ready(function(){ /* Set breakpoint indicator */ var bp = funcs.get_breakpoint(); /** * If not a narrow screen width, * change the slideshow slides to standard size */ if( bp > 1 ){ funcs.set_slides( bp ); } /* Initialize slideshow */ funcs.slideshow_init(); /* Window resize or orientation change */ $(window).on('resize orientationchange', function(){ /* Get the new breakpoint */ var new_bp = funcs.get_breakpoint(); /* Check if bp requires different slideshow size */ funcs.set_slides( new_bp ); }); });
Summary
One thing that you will notice is that besides removing the .flexslider data object, I’m also removing flexslider’s slideshow pager, which it generates dynamically.
So that we don’t replace and reinitialize the slideshow every time the window is resized, a class is applied to the wrapping div. The slideshow is only modified if the screen width crosses a “breakpoint level”. For more information about my use of these breakpoint levels, see my last blog post, Responsive Breakpoints for jQuery.
I’m very thankful that I stumbled on Matt’s solution. You can see that I’ve done things a little differently. In the end we both end up with a slideshow that works for a responsive web design. If you have any questions about what I’ve done, please leave a comment.
andy says:
Do you have a sample website using this solution please?
Alan says:
I own you a coffee or a beer
Andy Dufresne says:
Hi, Blow the “Reader comments” heading, image is not displaying because you have not close the image tag.