nolimits4web / swiper

Most modern mobile touch slider with hardware accelerated transitions
https://swiperjs.com
MIT License
39.87k stars 9.75k forks source link

Swiper Infinite loop scroll jumping #7270

Open deividisss opened 10 months ago

deividisss commented 10 months ago

Check that this is really a bug

Reproduction link

https://codesandbox.io/p/sandbox/yl6ddq

Bug description

As an example, I will use the Slider Infinite Loop demo with 9 slides: https://swiperjs.com/demos/200-infinite-loop/core. When you press the back button arrow to go from the first slide to the last slide and then press pagination dot to go from slide 9 to slide 8, you will notice a crazy jump through multiple slides, and it keeps happening when you switch between slides 8 and 9 using pagination dots.

Expected Behavior

Slider should scroll one slide

Actual Behavior

It scrolls multiple slides https://github.com/nolimits4web/swiper/assets/48391144/0392a2c5-9847-44dd-9076-e4aed34486f5

Swiper version

v11.0.5

Platform/Target and Browser Versions

Windows /Linux Version 120.0.6099.111 (Official Build) (64-bit)

Validations

Would you like to open a PR for this bug?

hajirasyafi commented 10 months ago

Yeah I can see it

hamzaejaz787 commented 9 months ago

I have same issue, only happens when using navigation to go from last to first then i clicking on any pagination in between and it jumps like crazy. Any help would be appriciated

rengarcia commented 9 months ago

Same here, I have the similar error :(

and-t commented 7 months ago

I wrote a quick fix to this issue, after dealing with it on production. For reference, my swiper configuration:

const swiper = new Swiper(".swiper", {
    modules: [Navigation, Pagination],
    slidesPerView: "auto",
    centeredSlides: true,
    spaceBetween: 15,
    grabCursor: true,
    loop: true,
    slidesPerGroup: 1,
    loopFillGroupWithBlank: false,
    loopAdditionalSlides: 2,
    lazy: {
        loadPrevNext: true,
        loadPrevNextAmount: 2,
    },
    keyboard: {
        enabled: true,
    },
    navigation: {
        nextEl: ".swiper-button-next",
        prevEl: ".swiper-button-prev",
    },
    pagination: {
        el: ".swiper-pagination",
        clickable: true,
    },
});

I really wanted a centeredSlides: true swiper with slidesPerView: "auto", but this meant that going backwards past index: 0 would generate a weird behavior (there would be a full loop, or jumping a few slides / indexes). Taking the slidesPerView: "auto" fixed the backwards jump, but now there was an issue going forward. So I wrote the following fix:

  1. First, you need a global (or scoped, depending on your code) variable:

let currentIndex = 0;

  1. Then, we need two custom functions for each swiper navigation button:
    
    const prevButton = document.querySelector(".swiper-button-prev");
    const nextButton = document.querySelector(".swiper-button-next");

prevButton.addEventListener("click", () => { if (currentIndex === 0) { currentIndex = swiper.slides.length - 1; } else { currentIndex--; } swiper.slideToLoop(currentIndex); console.log(currentIndex); });

nextButton.addEventListener("click", () => { currentIndex = swiper.realIndex; console.log(currentIndex); });


This will eliminate the issue of the realIndex jumping like crazy when going backwards. If your issue appears when going forward on the slide, swap the functions.
shalevc1098 commented 7 months ago

I wrote a quick fix to this issue, after dealing with it on production. For reference, my swiper configuration:

const swiper = new Swiper(".swiper", {
    modules: [Navigation, Pagination],
    slidesPerView: "auto",
    centeredSlides: true,
    spaceBetween: 15,
    grabCursor: true,
    loop: true,
    slidesPerGroup: 1,
    loopFillGroupWithBlank: false,
    loopAdditionalSlides: 2,
    lazy: {
        loadPrevNext: true,
        loadPrevNextAmount: 2,
    },
    keyboard: {
        enabled: true,
    },
    navigation: {
        nextEl: ".swiper-button-next",
        prevEl: ".swiper-button-prev",
    },
    pagination: {
        el: ".swiper-pagination",
        clickable: true,
    },
});

I really wanted a centeredSlides: true swiper with slidesPerView: "auto", but this meant that going backwards past index: 0 would generate a weird behavior (there would be a full loop, or jumping a few slides / indexes). Taking the slidesPerView: "auto" fixed the backwards jump, but now there was an issue going forward. So I wrote the following fix:

  1. First, you need a global (or scoped, depending on your code) variable:

let currentIndex = 0;

  1. Then, we need two custom functions for each swiper navigation button:
const prevButton = document.querySelector(".swiper-button-prev");
const nextButton = document.querySelector(".swiper-button-next");

prevButton.addEventListener("click", () => {
    if (currentIndex === 0) {
        currentIndex = swiper.slides.length - 1;
    } else {
        currentIndex--;
    }
    swiper.slideToLoop(currentIndex);
    console.log(currentIndex);
});

nextButton.addEventListener("click", () => {
    currentIndex = swiper.realIndex;
    console.log(currentIndex);
});

This will eliminate the issue of the realIndex jumping like crazy when going backwards. If your issue appears when going forward on the slide, swap the functions.

how can i fix it with react?

joey-ma commented 5 months ago

still an issue today. Tried to implement this with solution proposed in thread @and-t, but couldn't produce the desired fix :( (I'm also using React)

deleanuradu commented 3 months ago

This is even more of a problem when using Swiper in a loop logo reel component, after the loop ends, the logos just jump a number of positions to the right. Here's my config:

const logosSwiperConfig: SwiperOptions = {
          effect: "slide",
          direction: "horizontal",
          spaceBetween: 60,
          centeredSlides: true,
          freeMode: true,
          speed: 7000,
          loop: true,
          slidesPerView: 7,
          loopAdditionalSlides: 7,
          allowTouchMove: false,
          autoplay: {
            delay: 0.5,
            disableOnInteraction: false
          },
          breakpoints: {
            // when window width is >= 320px
            320: {
              slidesPerView: 2,
              loopAdditionalSlides: 2,
              spaceBetween: 20
            },
            // when window width is >= 480px
            480: {
              slidesPerView: 3,
              loopAdditionalSlides: 3,
              spaceBetween: 30
            },
            // when window width is >= 640px
            640: {
              slidesPerView: 4,
              loopAdditionalSlides: 4,
              spaceBetween: 40
            },
            1000: {
              slidesPerView: 7,
              loopAdditionalSlides: 7,
              spaceBetween: 60
            }
          },
          on: {
            init: (swiper: Swiper) => {
              this.swiperLogos = swiper;
            },
          }
        };
and-t commented 3 months ago

This is even more of a problem when using Swiper in a loop logo reel component, after the loop ends, the logos just jump a number of positions to the right. Here's my config:

const logosSwiperConfig: SwiperOptions = {
          effect: "slide",
          direction: "horizontal",
          spaceBetween: 60,
          centeredSlides: true,
          freeMode: true,
          speed: 7000,
          loop: true,
          slidesPerView: 7,
          loopAdditionalSlides: 7,
          allowTouchMove: false,
          autoplay: {
            delay: 0.5,
            disableOnInteraction: false
          },
          breakpoints: {
            // when window width is >= 320px
            320: {
              slidesPerView: 2,
              loopAdditionalSlides: 2,
              spaceBetween: 20
            },
            // when window width is >= 480px
            480: {
              slidesPerView: 3,
              loopAdditionalSlides: 3,
              spaceBetween: 30
            },
            // when window width is >= 640px
            640: {
              slidesPerView: 4,
              loopAdditionalSlides: 4,
              spaceBetween: 40
            },
            1000: {
              slidesPerView: 7,
              loopAdditionalSlides: 7,
              spaceBetween: 60
            }
          },
          on: {
            init: (swiper: Swiper) => {
              this.swiperLogos = swiper;
            },
          }
        };

@deleanuradu I can't replicate your issue. It works well for me.

jrvanstone commented 2 months ago

Any fix for this yet?

StarsLeopard commented 2 months ago

I'm running into this issue as well

StarsLeopard commented 2 months ago

I need to click on the pagination to move in the right direction, but occasionally it moves in the opposite direction

StarsLeopard commented 2 months ago

image Maybe when we clicking the Previous or Next button of the currently active pagination, we can use slidePrev or slideNext instead of slideToLoop,it could fix this problem @nolimits4web

teoeugene commented 2 months ago

In my situation, I have a swiper with slidesPerGroup = 1 and slidesPerView = 3. I don't have loop enabled but if I use the built-in navigation, instead of navigating 1 slide at a time, it moves multiple slides instead. The workaround I did for this is to have separate buttons to manually controlling the slides via the slidePrev and slideNext methods.