jQuery UI CoverFlow 2.0 Using $.widget

Hey guys. Today I would like to show you how to create and use a jQuery UI CoverFlow component powered by $.widget and CSS3 transforms. It’s highly extensible, supports click, keyboard and mousewheel interaction and works with the latest versions of both jQuery and jQuery UI (1.4.4 and 1.8.6 respectively).

The iTunes CoverFlow effect is one of my favorite user-interface patterns – it’s excellent for navigating around large collections of images (or data represented by images) and I thought it would be of great benefit to put out an updated version of this component out there.

If you would like to take a look at a demo or download the sources feel free to grab them below or at the end of this post.






CoverFlow: A History Of Implementations


You may be surprised to know that there’s been quite a substantial body of work that has gone into bringing the CoverFlow effect to the web over the past few years. 

The CoverFlow effect was originally conceived by Andrew Coulter Enright and implemented by independant Mac developer Jonathan del Strother in 2005. In 2006, Apple purchased the rights to CoverFlow and began including it in their bundled OSX applications, beginning with iTunes 7.0.

Ever since then we in the web development community have been fascinated with bringing this component in all it’s glory to the web. This has however been (and continues to be) something of a challenging feat.

When you look at the iTunes CoverFlow (see above) the first thing you’ll notice is that it’s almost 3D in nature. The shape of it’s covers are presented like trapeziums and there’s a level of depth to it that’s quite essential to the effect being correctly implemented. Striking the right balance in the CoverFlow’s ‘stack’ animation is also quite important for getting it right.

Before we go about building a new CoverFlow component, let’s take a look at how CoverFlow on the web has evolved over the years first for some context (feel free to skip this section if you would like to get right into the implementation being released today).

PHP + GD/ImageMagick (2006-2008)

The earliest attempts at implementing CoverFlow relied quite heavily on server-side image processing. The images one wished to be rendered as CoverFlow’s trapezium ‘covers’ would be stored on the sever, then read through a PHP script which would perform image-processing on your picture and then dump it back to the browser with the correct shapes, angles and depth in place.

The downsides to this were that CoverFlow is actually quite animation-focused and just rendering a single frame of this animation meant you lost quite a lot of the elegance CoverFlow had to offer. Server-side image processing is also not very efficient and I generally disapprove of using it in lieu of client-side alternatives.

Flash (2007)

Once developers realized the limitations of a pure PHP solution, they turned their heads to using Adobe’s Flash to implement the CoverFlow effect instead. Despite any criticisms we may have about Flash itself, a few years ago it was actually quite a decent framework for user interface ideas requiring math, transformations and even light image processing.

The Flash Coverflow implementations that were created would have been perfect but a non-plugin approach that was more ‘lightweight’ was still desired so our efforts again continued in search of a better approach to implementation.

JavaScript + Canvas Element (2007-2010)

From a development perspective the Canvas element is ideal for CoverFlow – it essentially has all the drawing capabilities you’d find in Flash with the added benefit of not requiring a plugin to view it in the browser. Trapeziums (arguably the most difficult part to get right in a CoverFlow) are also trivial to draw using canvas and as it seamlessly interacts with JavaScript, such implementations are quite easily extensible.

I created my first Canvas based CoverFlow component about two years ago and released an improved version last year.  Canvas implementations of CoverFlow remain quite viable but their major drawback is that they aren’t as consistently fast nor as snappy as the next option I’ll be presenting.

jQuery CSS3 CoverFlow (2008-2010)

When implementing CoverFlow a developer always has to bare in mind that unlike a simple carousel, each ‘cover’ in a CoverFlow actually has to have it’s various depth and angular properties updated when you switch between covers. This is usually an expensive operation to achieve (if you’re using Flash or Canvas) but significantly less so when using CSS3.

CSS3 supports a number of transformations (include matrix transformations) which make it possible for us to ‘transform’ an image into a shape which closely resembles a trapezium. Through JavaScript (jQuery) we are then able to dynamically generate the transformation parameters required for each ‘cover’ in a relatively straight-forward manner anytime a user skips to the next or previous covers.

For today’s release, I revisited an experimental CSS3 CoverFlow project by the very talented Paul Bakaus which was released a few years ago. With this I’ve made a number of both visual and internal changes to it to make it more ‘CoverFlow’ like as I felt it was missing some of the depth and anglular requirements for the effect.

I also introduced a synchronized playlist and interaction features to the project, but one important update was that the component now works with jQuery 1.4.4 and jQuery UI 1.8.6.

This re-write will allow you to use the component in any new projects without any trouble.

Lets take a look at how the component was created.


Coding CoverFlow With The jQuery UI Widget Factory Using $.widget

The UI Widget Factory is a part of the jQuery UI Library that provides easy-to-use, object oriented ways to create jQuery plugins that are stateful – the new CoverFlow component is built using this. A stateful plugin is an advanced plugin that is considered self-aware. They maintain both their own state and they also often provide external interfaces that allow code outside of the plugin to interact with it’s state.

Widgets (another name for plugins that are stateful – known thus as we use $.widget to create them) often trigger events and offer callback hooks that connect with important aspects of their functionality. Plugins of this nature often focus on solving specific tasks and can be both very simple or quite complex. Examples of the latter include widgets like the Sliders and Dialogs you find in jQuery UI.

The Widget Factory is quite useful as it offers consistent, well defined structures for creating and interacting with stateful plugins. Remember that you don’t have to use the Factory to create a stateful plugin, however it does simplify the process by setting up a standard configuration. When using the Widget Factory the one thing to remember is that your end product isn’t a jQuery UI Widget – it’s still a jQuery plugin, albeit one with an API similar to jQuery UI.

The benefit of this is that developers who use your plugins may find it easier to learn how to use them and work with your plugin’s codebase.

Let’s Get Started With $.widget

To create our CoverFlow component using the Widget Factory, we’re first going to take a look at the standard structure of a Widget Factory $.widget plugin. For ease of understandability you can find inline comments that explain the different parts of the plugin in the code sample below.

Notes: The following default methods are available for each instance of a $.widget plugin:

  • destroy(): Removes the instance from the encapsulated DOM element, which was stored on instance creation
  • option(String key[, String value]): Gets or sets an option for this instance
  • enable(): Set disabled option to false, it’s up to the instance to respect the option
  • disable(): Set disabled option to true, it’s up to the instance to respect the option

and the following property is also available by default:

  • options: The options for this widget instance, a mix of defaults with settings provided by the user
$.widget('namespace.nameOfPlugin', {
            // default options
             options: {
                     value: 10,
                     display: false
 _create: function(){
    // anything called on initialization of the plugin
    //this.options is a combination of the defualt options and the ones passed in during the plugin initialization
                      //here is an example of using this.options
        if (this.options.display) {
            //check the display parameter
    _someprivatemethod: function(value) {
        //private internal functions
        //note: private functions should be named with a leading underscore
        //as will only be able to be called from inside the plugin
                      //here we will return whatever value is passed + 100.
                      return value + 100;
    somepublicmethod: function() {
        //this is a public function that can be called outside of the plugin
        //calling the private method from inside the public method
    value: function(value) {
        //this is a public function that is defined as a getter
        //meaning it returns a value and not a jQuery object
                     // no value passed, act as a getter
                         if (value === undefined) {
                             return this.options.value;
                            // value passed, act as a setter
                         } else {
                         this.options.value = this._someprivatemethod(value);
    destory: function() {
        $.widget.prototype.apply(this, arguments); // default destroy
        //this is where you might want to undo anything applied to the page

With the above structure you can then simply call the following to initialize the plugin you have created:


You can also call the public methods (such as ‘somepublicmethod()’) as follows, once the plugin has been initialized:

//Initializing the plugin with a default value
$('#myelement').nameOfPlugin({ value: 70 };
//Get the current value of value (a getter action)
//Set the current value of value (a setter action)
$('#myelement').nameOfPlugin('value’, 45);

As you can see, creating stateful jQuery plugins doesn’t take very long at all and $.widget provides a convenient way to write widgets that follow a structure which can be a little easier to follow than plugins which don’t necessarily follow any set structures or design patterns.

If you would like to read up more on using $.widget, I recommending reading the following chapter of Rebecca Murphy’s jQuery Fundamentals book.


Implementing & Using CoverFlow

In this section I will be taking you through some of the core code involved in creating and using CoverFlow.

Digging Into CoverFlow


There are many different functions used to generate the overall CoverFlow animation effects but two of the core functions defined are called select() and _refresh(). select() performs the animation step when you select a CoverFlow item whilst what refresh() does is it regenerates the transformation information needed for a cover when you perform an action such as initializing the CoverFlow or clicking on a Cover to bring it into the main view.

What we’re doing in the below code sample is firstly establishing whether a cover is on the right or left of the CoverFlow (slightly different parameter values are used depending on which side). We’re then setting a z-Index for the cover relative to how high up the side’s stack an image is and then calculating the transformation matrix and scale values needed to shape the image in the form of a trapezium.

Note that vendor prefixes to be used are also set here depending on the browsers supported/being used.


	select: function(item, noPropagation) {
		this.previous = this.current;
		this.current = !isNaN(parseInt(item,10)) ?
		parseInt(item,10) : this.items.index(item);
		//If clicking on the same item, don't animate
		if(this.previous == this.current) return false;
		//Required: Overwrite the $.fx.step.coverflow everytime with
		//a custom scoped values for this specific animation
		var self = this, to = Math.abs(self.previous-self.current) <=1 ?
		self.previous : self.current+(self.previous < self.current ? -1 : 1);
		$.fx.step.coverflow = function(fx) { self._refresh(, to, self.current); };
		// Stop the previous animation from running
		// Animate the parent's left/top property so
		//the current item is in the center
		// Use our custom coverflow animation which animates the item
		var animation = { coverflow: 1 };
		animation[this.props[2]] = (
			(this.options.recenter ? -this.current * this.itemSize/2 : 0)
			//Center the items container
			+ ( ? this.element.parent()[0]['offset'+this.props[1]]/2 - this.itemSize/2 : 0)
			//Subtract the padding of the items container
			- ( ? parseInt(this.element.css('padding'+this.props[3]),10) || 0 : 0)
		//Trigger the 'select' event/callback
		if(!noPropagation) this._trigger('select', null, this._uiHash());
		//Perform animation routine with easing.
		this.element.stop().animate(animation, {
			duration: this.options.duration,
			easing: 'easeOutQuint'


   var side = (i == to && from-to < 0 ) ||
   i-to > 0 ? 'left' : 'right',
    mod = i == to ? (1-state) : ( i == from ? state : 1 ),
    before = (i > from && i != to),
    css = { zIndex: self.items.length +
    (side == "left" ? to-i : i-to) };
    css[($.browser.safari ? 'webkit' : 'Moz')+'Transform'] =
   'matrix(1,'+(mod * (side == 'right' ? -0.2 : 0.2))+',0,1,0,0) scale('+(1+((1-mod)*0.3)) + ')';
   css[self.props[2]] = ( (-i * (self.itemSize/2)) + (side == 'right'? -self.itemSize/2 : self.itemSize/2) * mod );
//handle browsers that don’t support transforms or
//aren’t supported by CF
   if(!supportsTransforms) {
       css.width = self.itemWidth * (1+((1-mod)*0.5));
       css.height = css.width * (self.itemHeight / self.itemWidth); = -((css.height - self.itemHeight) / 2);

If you would like to dig deeper into the code, check out ui.coverflow.js in the release folder as this contains all of the code for this particular jQuery UI plugin.


Using CoverFlow

To use CoverFlow we first need to define a list of items which we which to use for our covers. This can be done using some simple HTML. We will also define some mark-up for the slider you see below the CoverFow as well as the image caption holder.


Sample Text


For the purposes of this tutorial we will not be covering the scrollable vertical playlist, but you can find full details of this in the source code download pack. Next we’ll define some default CSS for the CoverFlow wrapper, the image list (#coverflow) and finally the image covers themselves.

div.wrapper {
   height: 390px;
   width: 800px; /*600*/
   padding: 10px;
   overflow: hidden;
   position: relative;
   margin: 0 auto;
#coverflow {
   height: 300px;
   width: 2600px;
   padding: 42px;
   position: absolute;
   top: 0px;
   left: 0px;
   margin-top: 50px;
#coverflow img {
   width: 260px;
   height: 260px;
   float: left;
   position: relative;
   margin: -35px;

Let’s now take a look at the JavaScript. As my demo includes quite a bit of additional interaction added on top-of it, I’ve kept all my code for it inside a separate app.js file. Let’s go through some of the core functionality defined here:

Initialization & Basic Navigation

       //cache core component references
       var html = $('#demo-frame div.wrapper').html();
       var imageCaption = $('#imageCaption');
       $('#demo-frame div.wrapper').parent().append(html).end().remove();
       $sliderCtrl = $('#slider');
       $coverflowCtrl = $('#coverflow');
       $coverflowImages = $coverflowCtrl.find('img');
       $sliderVertical  = $("#slider-vertical");
       //app defaults
       var defaultItem  = 0;
       var listContent = "";
      //Set the default image index.
      //Set the default item to display on load.
      //Correct indexing
      function setDefault($n){
         defaultItem = $n-1;
      //set the image caption
      function setCaption($t){
       //Initialize CoverFlow
           item: defaultItem,
           select: function(event, sky)
      //Initialize Horizontal Slider
           min: 0,
           max: $('#coverflow > *').length-1,
           value: defaultItem,
           slide: function(event, ui) {
               $coverflowCtrl.coverflow('select', ui.value, true);
               $('.coverflowItem:eq(' + (ui.value) +')').addClass('ui-selected');
               setCaption($('.coverflowItem:eq(' + (ui.value) +')').html());
      //Skip to an item in the CoverFlow
      function skipTo($itemNumber)
         $sliderCtrl.slider( "option", "value", $itemNumber);
         $coverflowCtrl.coverflow('select', $itemNumber, true);
         $('.coverflowItem:eq(' + ($itemNumber) +')').addClass('ui-selected');
         setCaption($('.coverflowItem:eq(' + ($itemNumber) +')').html());
       //Skip all controls to the current default item
       //Assign click event for coverflow images
       $('body').delegate('.coverflowItem','click', function(){

Keyboard Navigation

       //Handle keyboard events (note: keydown is used rather than
       //keypress as Chrome/Webkit has known issues using the latter)
         $current = $sliderCtrl.slider('value');
            case 37:
            if($current > 0){
            case 39:
            if($current < $('#coverflow > *').length-1){

MouseWheel Support

$(document).mousewheel(function(event, delta){
var speed = 1;
var sliderVal = $sliderCtrl.slider("value");
var coverflowItem = 0;
var cflowlength = $('#coverflow > *').length-1;
//check the deltas to find out if the user
//has scrolled up or down
if(delta > 0 && sliderVal > 0){
          sliderVal -=1;
         if(delta < 0 && sliderVal < cflowlength){
          sliderVal +=1;
//calculate the content top from the slider position
var leftValue = -((100-sliderVal)*difference/100);
//stop the content scrolling down too much
if (leftValue>0) leftValue = 0;
//stop the content scrolling up beyond point desired
if (Math.abs(leftValue)>difference) leftValue = (-1)*difference;
  coverflowItem = Math.floor(sliderVal);
//stop any default behaviour


Demos and Downloads Demo, Source, Github link.

You can try out a demo of CoverFlow below or download all the sources for today’s release. Alternatively if you would like to make your own changes to the CoverFlow source you can use the GitHub link below to fork the project.





And that’s it!. Thanks for checking out this article – I hope it helps!. If you’ve found it useful please feel free to share it with your friends and colleagues just by hitting the retweet button below. Until next time, good luck with all your JavaScript projects!.

– Addy.


  1. Nice package, thanks for releasing it !

    It seems though your perspective is wrong.

    Check out a website we released a while back : we did an iPhone specific version with coverflow using transform3d (user agent sniffing for iPhone)

    Our version is not widgetized, but has better performance & perspective

    Feel free to reuse parts ! (we did…)

    • I checked out the ZoomViewer that they have on their site (I assume this is what you were referring to) but it appears that they're using pre-rendered graphics for each of the covers. A proper coverflow implementation wouldn't have this pre-requisite and would rather generate the trapeziums dynamically – were you referring to something other than the ZoomViewer? :)

  2. Pingback: links for 2010-11-23 | Midashuang's Blog

  3. Nice effect, but doesn't work properly in IE8. Firstly the caption text is overlayed by the images, and the image positioning wanders. In Firefox, each image is more or less centered over the slider bar. In IE8 however, the first image in the list, image 0 is centered, image 1 is positioned slightly to the right of center, image 2 further right etc etc

    • Hey Ben. I probably should have made it more clear in the post, but this won't work in IE8. I intend on improving the cross-browser compatibility of the component with the next release, but as I'm sure you can appreciate, since this currently relies on CSS3 features in order to generate the full effect, what IE8 users will experience will be a bare-bones version even with the next iteration. Not a bad proof of concept though :)

      • The basics worked for me even in IE7 once I set the scale as follows in the transform:
        scale('+(.7+((1-mod)*0.3)) + ')
        Hope that doesn't screw anything else up too much.

  4. Pingback: links for 2010-12-13 « B I T Z

  5. Except it rotates the cover on the wrong axis, isn't fluid and doesn't behave in the same way. If I had time between ragechat and working for a living I'd make a better one, but I suppose it will do for a quick fix if you really needed this.

    • A quite obnoxious reply. I imagine also Addy has a work and other things to do. But he took the time and care to share. You did..? Nothing. Please, disappear.

    • in image tag add onclick="clickedImage('weezer')" and for the function
      var lastClick = "";
      function clickedImage(what) {
      if (what == lastClick) {
      window.location.href = ";;
      lastClick = "";
      } else {
      lastClick = what;
      its a hack but the point is the same.
      I am sure that some better condition could be tested though.

  6. Hi, Super Work…
    Just a little notice..
    I tried adding more album arts..when it got to the 14th one, it stopped showing..
    I want to be sure its not me causing the error.
    pls check.

  7. Very exciting. I have been doing this with an open source flash project but I am so sick of working with flash. This is perfect, with the flash version of the cover flow effect I needed to boot into windows just to use adobe flash editor when i needed to edit the source. This is so much better. Who needs adobe anyway? 😉 But seriously, I just wrote like five minuets of JavaScript and I have a function that handles a click event on the images once they are centered. I do some testing with transparency and it WORKS! I couldn't be happier. Whats the license on this BTW?

    • At the moment I haven’t had a chance to bake in an alternative view in for IE given that it doesn’t support CSS3 in older versions. I may have it default to a standard slider!

  8. This is a great set of code, I've been trying to find a way to make a scrolling gallery. I'm just starting to code websites so some of this is way over my head. Is there a way to have the user click on an image and it would open it in a shadow box? or have each image be a separate gallery and then upon clicking open another slider with images related to the gallery?

    I know I'm asking questions way over my head, but this is the only way to learn, Thanks so much for posting this.

  9. Nice, but I am surprise nobody seem to notice the strange shape of the covers. Just look at the sketch and the next image at the beginning of the section "Implementing & Using CoverFlow". The images on the sides do not correspond, and this makes quite a visual difference when flowing.

  10. Nice work.
    I have to add more than 13 images. I am facing the same problem that had been mentioned before, when i add 14 images, 14th image is not shown..
    Whats the problem behind that?

    Any help will be appreciated.

  11. I misposted above, sorry, reading previous comment. My question is how do you adjust the starting point of the coverflow when having fewer than 13 images? For example when I have 5 images the initial position is after the last image.

    Thanks for the great tool!

  12. Is there an option to detect which image has focus (has been selected)? Then assign a href link to it, so if clilcked again it activates the href?

  13. Nice job on the coverflow widget. I've modified the body of the _refresh to work with IE. Here's the modification:


    css[($.browser.safari ? 'webkit' : 'Moz')+'Transform'] = 'matrix(1,'+(mod * (side == 'right' ? -0.2 : 0.2))+',0,1,0,0) scale('+(1+((1-mod)*0.3)) + ')';

    css[self.props[2]] = ( (-i * (self.itemSize/2)) + (side == 'right'? -self.itemSize/2 : self.itemSize/2) * mod );


    css["filter"] = "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=1, M12=0, M21=" + (mod * (side == 'right' ? -0.2 : 0.2)) + ", M22=1";
    css[($.browser.safari ? 'webkit' : 'Moz')+'Transform'] = 'matrix(1,'+(mod * (side == 'right' ? -0.2 : 0.2))+',0,1,0,0) scale('+(1+((1-mod)*0.3)) + ')';

    css[self.props[2]] = ( (-i * (self.itemSize/2)) + (side == 'right'? -self.itemSize/2 : self.itemSize/2) * mod );

    if(i == self.current){
    css.width = self.itemWidth * (1+((1-mod)*0.3));
    css.height = css.width * (self.itemHeight / self.itemWidth); = -((css.height – self.itemHeight) / 3);

    css.left -= self.itemWidth/6;
    css.width = self.itemWidth;
    css.height = self.itemHeight; = 0;

    if(side == "left")
    css.left -= self.itemWidth/5;
    }//end if
    }//end if

  14. To get the same functionality in Opera do the following:


    var supportsTransforms = !($.browser.mozilla && (parseFloat(browserVersion) <= 1.9)) && !$.browser.opera;


    var supportsTransforms = !($.browser.mozilla && (parseFloat(browserVersion) <= 1.9));

    Then find:

    css[($.browser.safari ? 'webkit' : 'Moz')+'Transform']

    And replace it with:

    css[($.browser.safari ? 'webkit' : ($.browser.opera ? 'O' : 'Moz'))+'Transform']

    Opera will support the full CSS matrix transform.

    • Hmm. While your opera changes work (as expected, it's an initial transform switch) the IE changes don't appear to render as well. Do you have an example of your updates being fully function around anywhere?

  15. Adding a note to self: There is *wayy* too much useragent checking going on in this plugin. Going to refactor one of the next iterations to not rely on this at all.

  16. Just a small correction…

    My version, xFlow! (first image above with Lizard in) only uses PHP to produce single thumbnails, not various angled ones. The rest of the operations are client side JS. The reason for this is simple, client side JS driven image manipulation can be incredibly resource hungry, and even with a 4gb machine I found some of them stuttering. xFlow! produces the thumbs, including the reflections, server side on initial gallery creation, not every time a page is loaded like the JS counterparts and delivers them to the page as required. Meaning transitions and animations should be a lot smoother. Basic web/html stuff.

    It's worked well so far and many people have been very happy with the results.

    I do like your JS version and I think you've done a great job with it. Currently mine is not jQuery, but it's a direction I'm looking for later releases.

    Feel free to check it out..

  17. Pingback: jQuery & CSS3でiTunes風のカバーフローUIを実装できる「jQuery UI CoverFlow 2.0 Using $.widget」 | BlackFlag

  18. Browser page mouse scroll does not work, if we enable mouse scroll for coverflow :(
    Could you please let me know how to fix this ?

  19. Yes I found the solution.

    $('#coverflow').mousewheel(function(event, delta){

    Instead of
    $(document).mousewheel(function(event, delta){


  20. Pingback: jQuery UI CoverFlow 2.0 | Simply-GFX.Co.Cc

  21. Pingback: 20款最新且极具创意的jQuery插件-传播、沟通、分享-一直“有你”

  22. Hi, nice work :)
    Can I control it (just move-right, move-left and select) calling a javaScript function? I need to control it using a socket, so I can only call functions… but, i don't know why, I can't call 'skipTo' function from a javaScript console…

  23. Brilliant Coverflow, Addy, thanks for sharing this.

    Quick question : it works like a charm on my mac book pro., but it's really slow on an iPad.
    any idea ?

    thanks a million.

  24. And yes, like Ayo said some time ago, the coverflow stops if more than 14 items are added in . Any idea on this ?


    • Hey Richard. Not at the moment but I may look into this for a future version. Right now there's already a mobile optimized CSS3 coverflow component out there that I've tested as working well (it may have been called CSS-VFX, though that could have just been one of many versions). If anyone would like to try their hand at integrating touch gestures into this widget version, by all means please go for it :)

  25. Hello,

    first of all… great project! I really like it :) I try to use it on a webpage of one of my clients but I got a problem. The selected image is always centered. But if I change the width of all images, it's not centered. You can see that, when clicking on the last image. The first image seem to be centered, but the last doesn't.

  26. @benjamin Try different values on line 55 of ui.coverflow.js:
    this.itemSize = 0.79 * this.items.innerWidth();
    That will fix it.

    @addy Do you know why some pictures start to "shake" for a second in IE7 after scrolling to any item in the coverflow?

    Or does anyone else know how to solve that?

  27. Hello Adday,
    This is awseme plugin, just love it.
    Btw, If I've more images(20+), and i extend the width of #coverflow, last images of the coverflow aren't aligned center, how can i fix that? I tried with @Michel tricks but that doesnt work.

  28. May I know if there is any way to control the sensitivity of mousewheel? It slides too much even with a little bit mousescroll.

  29. Hello,
    I am using this same Plugin for one of my projects. I cannot figure out how to implement the Next and Previous buttons instead of the Slider. I am not a jquery developer, but I am learning. Can someone please help?

    Thanks you so much.

Leave a Reply

Required fields are marked *.