question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Infinite loop with slidesPerView: auto, loopFix() issues

See original GitHub issue

This is a (multiple allowed):

  • bug

  • enhancement

  • feature-discussion (RFC)

  • Swiper Version: 4.4.6 (also tested 4.4.x versions and the problem persists)

  • Platform/Target and Browser Versions: all platforms and browsers I’ve been testing: Windows/Android and Chrome/Opera/Firefox (the most actual versions)

  • Live Link or JSFiddle/Codepen or website with issue: -“big case” codepen -“small/simplified case” codepen

What I did

I use swiper with the following settings (the “big case”):

autoplay: {
    delay: 0
},
centeredSlides: true,
coverflowEffect: {
    depth: 100,
    modifier: 1,
    rotate: 5,
    stretch: 0
},
effect: 'coverflow',
freeMode: true,
freeModeMomentumBounce: false,
freeModeMomentumRatio: .1,
freeModeMomentumVelocityRatio: .8,
freeModeSticky: true,
grabCursor: true,
loop: true,
loopAdditionalSlides: slidesNum, // slidesNum contains the initial slides number
loopedSlides: slidesNum,
slidesPerView: 'auto',
speed: 20000,
breakpoints: {
    360: {
        slidesPerView: 1
    }
}

+some css styles (I did put them in codepens). After some experiments I’ve managed to recreate the issue only with these settings (the “small case”):

centeredSlides: true,
loop: true,
loopedSlides: slidesNum,
slidesPerView: 'auto',

I don’t know if solving problem for the “small case” will be sufficient for solving the “big case”, but for sure it’s a good way to start.

Behavior

If I slide to the left, everything seems fine (unless the screen is very big or there are too few slides, i.e. 2), but when I swipe to the right, duplicated elements won’t show up on the right side of the slider, which causes a huge empty space after the slides. It’s even worse if I swipe very fast (it may cause the whole container to be empty for a moment). Occasionally the slider updates and the duplicates “jump in” to the right place, but it’s too soon, so it looks bad and may be confusing for the user.

I could find some similar issues here on GitHub, but none of the presented fixes worked for me. For instance I’ve been playing with loopedSlides and loopAdditionalSlides options (i.e. I’ve been trying to put there some huge values like slidesNum, 2 * slidesNum, 10 * slidesNum, 50 or slidesNum - 1, where slidesNum contains the initial slides number). It didn’t help.

Moreover I’ve got impression that changing loopAdditionalSlides value option is doing literally nothing. In the docs it’s said that it’s the “number of slides that will be cloned after creating of loop”, but as far as I could see, number of cloned slides is always equal to the number of original slides - please correct me if I’m wrong. So technically, how does this option work?

The other thing I’ve tried was translating the slider manually when the very last slide appears on the screen, but then I had problems with smooth movement/free mode momentum (see “Big case”).

Attemption to fix this

I’ve been trying to modify swiper.js script in order to make it work. First of all I’ve noticed that the method loopFix is responsible for “fixing” the loop (to be more specific it handles the translation of slider if some conditions are met). These conditions look like this:

if (activeIndex < loopedSlides) {
    // Fix For Negative Oversliding
} else if ((params.slidesPerView === 'auto' && activeIndex >= loopedSlides * 2) || (activeIndex >= slides.length - loopedSlides)) {
    // Fix For Positive Oversliding
}

First of all I replaced the 2 multiplier in the second condition with 1 (to tell the truth I couldn’t understand why the 2 is there, as activeIndex >= loopedSlides is the opposite condition to the activeIndex < loopedSlides). Can some good soul explain me why there is 2? Thanks!

Secondly I used the console.log and observed that the first condition for negative oversliding was sometimes fulfilled even though I was swiping to the positive direction, so I decided to fix this by imposing some additional condition here related to the sliding direction. So I got something like this:

var previousIndex = swiper.previousIndex;
var dir = (activeIndex > previousIndex) ? 'right' : 'left';

if (dir === 'left' && activeIndex < loopedSlides) {
    // Fix For Negative Oversliding
} else if (dir === 'right' && ((params.slidesPerView === 'auto' && activeIndex >= loopedSlides) || (activeIndex >= slides.length - loopedSlides))) {
    // Fix For Positive Oversliding
}

In general this fix may not be sufficient for some RTL settings, but it helped a little bit in my case. Here is an example: “attemption to fix” codepen.

As you can see it may seem to work now, but there are still some problems:

  • variable dir has got wrong value after first swipe in the opposite direction (for example if we are swiping left and then we swipe right for once, the dir variable still evaluates to ‘left’ not to ‘right’; it’ll have the correct value ‘right’ only if we swipe right for the second time and further). So the problem still may occur in these kinds of situations.
  • fast swiping can still cause swiper container to be partially empty; in the worst scenario I could limit the maximum slider speed, but it’s not very user friendly
  • (hard to reproduce) I’m not sure if it concerns the small case, but for the big case in Opera and Chrome browsers some random swiping may cause an infinite script loop (more precisely the method swiper.loopFix(); in line 3038 of the swiper.js (ver. 4.4.6) starts to run infinitely, causing the whole slider to freeze).

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:16
  • Comments:19

github_iconTop GitHub Comments

9reactions
Lighttreecommented, Nov 19, 2019

Have the same issue:

const swiperInstance = new Swiper(containerRef.current, {
            direction: 'horizontal',
            slidesPerView: 'auto',
            loopedSlides: 3,
            loop: true
});

With following config Swiper correctly work to the left left, but not to the right.


UPD:

I think the issue reproducible when width of all the slides (not cloned) less than width of “viewport”.

5reactions
nadamaicommented, Apr 12, 2019

Ok, I think I fixed the major problems in my case (but it may not be sufficient in general).

  1. I modified first condition like this: if (dir === 'left' && activeIndex < loopedSlides && !(activeIndex === previousIndex - 1 && previousIndex > loopedSlides / 2)) {

  2. I added an argument “direction” to the loop fix method, which can be “left”, “right” or undefined: function loopFix (direction) {

  3. I modified the conditions once again, taking the argument into account:

if ((typeof direction === 'undefined' || (typeof direction !== 'undefined' && direction === 'left')) && activeIndex < loopedSlides && !(activeIndex === previousIndex - 1 && previousIndex > loopedSlides / 2)) {
    // Fix For Negative Oversliding
} else if ((typeof direction === 'undefined' || (typeof direction !== 'undefined' && direction === 'right')) && (params.slidesPerView === 'auto' && activeIndex >= loopedSlides) || (activeIndex >= slides.length - loopedSlides)) {
    // Fix For Positive Oversliding
}
  1. I passed an argument to this method in following places:
  • changed swiper.loopFix(); to swiper.loopFix('right'); in slideNext method
  • changed swiper.loopFix(); to swiper.loopFix('left'); in slidePrev method
  • changed swiper.loopFix(); to swiper.loopFix('right'); in the Autoplay variable initialization (but in general the argument here should be dependant on initial slider direction)
  • and the most complicated one; in method onTouchMove I have added var diff = swiper.isHorizontal() ? diffX : diffY; right before the if (!data.isMoved) { condition and then changed the next swiper.loopFix(); to swiper.loopFix(diff > 0 ? 'left' : 'right');

The last point is done like this, because I couldn’t get the correct swipe direction in the loopFix method (as stated in the previous post).

Additionally I commented out this fragment:

if (needsLoopFix) {
    swiper.once('transitionEnd', function () {
        swiper.loopFix();
    });
}

as sometimes it was causing the slider to freeze (the loopFix method was called infinitely, I don’t know why).

codepen: https://codepen.io/stasiak/pen/pGvGaq

Read more comments on GitHub >

github_iconTop Results From Across the Web

Infinite loop with slidesPerView: auto, loopFix ... - CodePen
<title>Infinite loop with slidesPerView: auto, loopFix() issues</title>. 5. <meta charset="utf-8">. 6. </head>. 7. <body>. 8. <div id="gallery-slider">.
Read more >
Why in the infinite loop the sliders in swiper js jump when the ...
I could not solve the following issue with swiper: I want to use the loop in this slider. In this slider, I have...
Read more >
Swiper Slider With Centered Auto And Continuous Infinite Loop
Issues kidjp85/reactidswiper GitHub A library to use idangerous Swiper Infinite loop with slidesPerView: auto loopFix issues Issue #2942.
Read more >
Swiper Changelog
core: fix issues with navigation/pagination enabled prop (af9ed85) ... core: better handle loop fix with cssMode enabled (ff84073); core: fix auto create ...
Read more >
Framework7 Release Notes
React/Svelte/Vue. ListInput. Fixed issue with infinite loop when updating calendarParams. Stepper. Auto update stepper internal value on value prop update.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found