5

I have a quick fiddle set up here. What I want is to be able to infinitely scroll to the left or right (carousel style) and just have the elements repeat (ie 'fall off' the right edge and re-appear on the left and vice versa). I'm able to capture where I am in the scroll but not sure what the best way to proceed after that is. It seems to me there is a very simple trick that is out there before I go down the route of trying to dynamically move elements.

CSS

#main {
    overflow-x:scroll;
    overflow-y:hidden;
    white-space:nowrap;
}

HTML

<div id="main">
    <img src="http://dummyimage.com/150x100/aaa/00f">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/000/fff">
    <img src="http://dummyimage.com/150x100/ccc/f00">
</div>

JS

$('#main').scroll(function (event) {
    var width = $(this)[0].scrollWidth - $(this).width();
    console.log('location: ' + $(this).scrollLeft() + ' out of ' + width);
});​
Abdullah Jibaly
  • 53,220
  • 42
  • 124
  • 197
  • So... when someone scrolls do the end, what should the scrollbar do? Just jump? I don't think that a scrollbar is suited for carousel scrolling. – Brilliand May 30 '12 at 07:45
  • I agree. Buttons either side would be better I think. Here's my attempt, scrolling left doesn't really work though. http://jsfiddle.net/ZgEZN/9/ – barro32 May 30 '12 at 07:53
  • This is for a mobile device, I don't want scrollbars. – Abdullah Jibaly May 30 '12 at 15:16

1 Answers1

5

This works reasonably well, scrollbar and all:

$('#main').scroll(function (event) {
    var factor = this.scrollLeft / (this.scrollWidth - $(this).width());
    if(factor < 0.2) {
        var move = $(this.lastChild);
        move.remove();
        $(this).prepend(move);
        this.scrollLeft += move.width();
    } else if(factor > 0.8) {
        var move = $(this.firstChild);
        move.remove();
        $(this).append(move);
        this.scrollLeft -= move.width();
    }
});

jsFiddle: http://jsfiddle.net/ZgEZN/10/

Scrolling to the leftmost or rightmost 20% of the scrollbar causes the scrollbar to behave funny, but not drastically glitchy. (Dragging the scrollbar to that area causes the carousel to spin rapidly until the scrollbar is either released or moved somewhere more reasonable. Scrolling to that area in some other way causes the scrollbar to jump back toward the middle.)

Brilliand
  • 13,404
  • 6
  • 46
  • 58
  • This looks pretty sweet. As I mentioned above I'm not showing the scrollbar anyways (on a mobile device). Only issue is that I can't scroll to the left immediately. – Abdullah Jibaly May 30 '12 at 15:19
  • This is truly brilliant! I just added a `$('#main').scrollLeft($('#main').children().last().width()/2)` so that the user can see that they can scroll either way. – Abdullah Jibaly May 30 '12 at 17:00
  • I just noticed that my jsFiddle produces a lot of console errors related to trying to get the width of a text node. It isn't a big problem, but if you have text nodes in your carousel, you should probably remove them: http://jsfiddle.net/ZgEZN/52/ (or wrap them in a span, if they're important) – Brilliand Mar 31 '15 at 17:02
  • When there are only 2 items or 3 in the carousel, and these items fit all the div content (1 item per slide), the scroll event is buggy. – Aral Roca Mar 30 '20 at 09:49
  • 1
    @AralRoca Yeah, I can definitely see how a small number of items would cause problems. The bigger the % of the scrollbar each item takes up, the more the weirdness of using a scrollbar for an infinite carousel shows itself. Duplicating all the items is a decent workaround, though. – Brilliand Mar 30 '20 at 19:35