nolimits4web / swiper

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

Next slide is not visible in a loop mode and slidesPerView set to more than 1 #7239

Open piotr-michalczuk-wttech opened 11 months ago

piotr-michalczuk-wttech commented 11 months ago

Check that this is really a bug

Reproduction link

https://jsfiddle.net/hk79p86y/8/

Bug description

Next slide is not visible on init and when using Navigation 'next' button when Swiper is set in a loop mode, slides are centered and value of slidesPerView is set to more than 1 e.g.:

slidesPerView: 1.2,
centeredSlides: true,
loop: true,

They get visible once I touch the slider. This behaviour can be observed for 3 slides. In my case it starts to work correctly if there are more than 3 slides.

To reproduce this issue I used example from resources - https://swiperjs.com/demos#centered within modified Swiper config options and number of slides.

Additional note: Worked as expected on Swiper v8.4.7 probably because of the fact that slides was duplicated.

Expected Behavior

For such a Swiper configuration:

slidesPerView: 1.2,
centeredSlides: true,
loop: true,

all slides that are defined by slidesPerView should be presented in view are visible right away on initialization or after slide change by Navigation 'next' button.

Actual Behavior

Next slide is not visible on init and when using Navigation 'next' button when Swiper is set in a loop mode, slides are centered and value of slidesPerView is set to more than 1.

Swiper version

11.0.5

Platform/Target and Browser Versions

macOS Chrome 119.0.6045.199

Validations

Would you like to open a PR for this bug?

chandra-sekharan commented 11 months ago

did you got any solution?

shkipan commented 11 months ago

I can confirm that this issue exists, faced the same problem yesterday. As the temporary solution I can suggest manual navigation between slides using slideTo swiper method with index recalculation. Worked for me

chandra-sekharan commented 11 months ago

In my case next duplicate slides are not showing but when we click on next navigation the slides showing

XavierCrespin commented 11 months ago

This is since V9 and the new loop behavior, it can be linked to the feature request I just posted : there are not enough duplicated slides, would help if we could set a number of duplicates.

daniel-agouveia commented 9 months ago

This issue is also happening in Angular, if I try to use slidesPerViewAuto with autoplay, autoplay won't work. V8 is working fine.

harrisondeo commented 9 months ago

I managed to fix this but in a VERY hacky way, You are correct @XavierCrespin that the issue happens when there is not enough slides to be greater than the amount per view.

I am using the React library but same solution should apply to others, I created a variable called "loopFixMode" which was true if my swiper had exactly 3 images (less than 3 I didn't want looping, more than 3 everything was ok), if loopFixMode was true and the index of the current slide is greater than slides.length - 1 then I set a different variable called loopFixFakeIndex = realIndex - slides.length(), I then used this variable within some custom pagination bullets and thumbnails.

I appreciate this solution only really works because I am using custom pagination and thumbs but I wanted to share incase tracking the "fake" index separate helped anyone else.

const [realIndex, setRealIndex] = useState(0)
const [loopFixFakeIndex, setLoopFixFakeIndex] = useState(0)
const loopFixMode = slides.length === 3

useEffect(() => {
   setLoopFixFakeIndex(realIndex > slides.length - 1 ? realIndex - slides.length : realIndex)
}, [slides.length, realIndex])

<Swiper
   onSlideChangeTransitionEnd={({realIndex: i}: {realIndex: number}) => setRealIndex(i)}
   onSlideChange={({realIndex: i}: {realIndex: number}) =>setRealIndex(i)}
   slidesPerView={"auto"}
   spaceBetween={10}
   centeredSlides
   loop
   roundLengths
   onInit={swiper => {
      swiper.slideToLoop(0, 0)
   }
 >
   {slides.map((slide, index) => renderSlide(slide, index))}
   {loopFixMode && slides.map((slide, index) => renderSlide(slide, slides.length + index))}
</Swiper>
<CustomPagination index={loopFixFakeIndex} />
<CustomThumbs index={loopFixFakeIndex} />
zemkogabor commented 7 months ago

Is there any update? I can confirm that the error mentioned above also occurs with the Vue library (loop + centeredSlides + multiple slidesPerView)

Luis-Kendelick commented 6 months ago

Is there any update, guys? I can confirm that this error occurs.

HarroH commented 6 months ago

Issue is also present when you have 1 slide per view. You just don't see it due to the overflow. If you remove the overflow you see the same issue:

https://jsfiddle.net/harro/7hvgym21/

jakub-gawronski-wttech commented 5 months ago

Hey, @nolimits4web - Issue still persists. I've recently seen that a warning appears in the console, regarding the number of slides. As a result of this check:

if (slides.length < slidesPerView + loopedSlides) {
      showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled and not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters');
    } else if (gridEnabled && params.grid.fill === 'row') {
      showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`');
    }

I've tried to dive a bit into this code and have some questions:

  1. Can you explain the logic behind this snippet?:

    let slidesPerView = params.slidesPerView;
    if (slidesPerView === 'auto') {
      slidesPerView = swiper.slidesPerViewDynamic();
    } else {
      slidesPerView = Math.ceil(parseFloat(params.slidesPerView, 10));
      if (centeredSlides && slidesPerView % 2 === 0) {
        slidesPerView = slidesPerView + 1;
      }
    }

    How is it that when I declare sliderPerView to 1.1 (so I can see one full slide and two small pieces of surrounding slides), it is being ceiled up to 2 and then bumped to 3 (+1 when centeredSlides && % 2)?

  2. What is loopedSlides in this context?:

    const slidesPerGroup = params.slidesPerGroupAuto ? slidesPerView : params.slidesPerGroup;
    let loopedSlides = slidesPerGroup;
    if (loopedSlides % slidesPerGroup !== 0) {
      loopedSlides += slidesPerGroup - loopedSlides % slidesPerGroup;
    }
    loopedSlides += params.loopAdditionalSlides;
    swiper.loopedSlides = loopedSlides;

    Default value for slidesPerGroup is 1. I'm not setting slidesPerViewAuto nor slidesPerGroupAuto, so I end up with the default 1. Then we're assigning this loopedSlides to the value of slidesPerGroup. Next line - it looks like some old thing, as line before we're making sure that both of these variables are equal, hence this % b thing will never happen, right? Then we're adding loopAdditionalSlides (which is 0 by default).

And after that, the initial block of code is being processed:

const gridEnabled = swiper.grid && params.grid && params.grid.rows > 1;
    if (slides.length < slidesPerView + loopedSlides) {
      showWarning('Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled and not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters');
    } else if (gridEnabled && params.grid.fill === 'row') {
      showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`');
    }

And I'd like you to explain, what is this loopedSlides in this context, since docs do not mention it at all.

Additionally, I'd love to understand, why having slidesPerView set to 1.1 which results in a situation, where total of 3 different slides are visible (in some part), causes this last statement to be true and breaks the loop mode (as in fiddle). With maximum of 3 slides visible we can't hit a moment, where potential 4th slide is visible at all (supposing the v11 way of loop moves the slide to the other side, when not needed on the opposing side).

Cheers.

cuneyt2002 commented 5 months ago

I have the same issue with the Next and Prev buttons. The next slide is only visible by dragging, but with the buttons, the loop slides are not visible. The only solution I have found is to change slidesPerView from 1 to 1.001. I hope there is a quick solution to this problem.

OnynAi commented 4 months ago

If it does not render properly or not visible try forcing the swiper container to have an overflow: hidden !important

In my case I am using styled library: const CustomSwiper = styled(Swiper, { shouldForwardProp: prop => prop !== 'isSmooth' })<{ isSmooth?: Boolean }>(({ isSmooth = false }) => ({ overflow: 'hidden !important', '& .swiper-wrapper': { transitionTimingFunction: isSmooth ? 'linear' : 'initial', }, }));

The cause of the issue might be: overflow: clip

I hope it helps!

shaobeichen commented 4 months ago

I met the same question

image

I find a temp method, I observed call swiper.loopFix can resolve it in swiperslidechange method, but can't use it in swiperslidechange, because it would recursion, so I use loopFix in watch effect,watch effect have cache, so it can avoidance recursion.

aderiushev commented 3 months ago

any updates on that? it is really annoying i have 1.1 slides pre view and there are 3 in total, why can't i do the infinite loop vs them..

PuffMeow commented 3 months ago

I got the same issue in v11.1.9

eastecho commented 2 months ago

Same here, tried v9+, got the same results. So, downgraded to v8.4.7, works as expected.

alexmillman23 commented 2 months ago

1721678121429737 i hate front-end. same issue. 3 slides set at per view of 1.333. Last one doesn't show until you scroll once.

peteratomic commented 2 months ago

Same for me... next slide doesn't show until touching a slide to grab it, then the next one pops in.

cuneyt2002 commented 2 months ago

Same here, tried v9+, got the same results. So, downgraded to v8.4.7, works as expected.

Use this version and add to your slidesPerView .001 to correctly loop with fewer than 3 slides.

flc995 commented 2 months ago

Had the same issue on Swiper 11.1.10, with 3 slides and loop: true What ended up fixing the issue is manually sliding to one slide after initializing swiper with slideToLoop. This is my code:

const swiper = new Swiper('.swiper-pros', {
  centeredSlides: true,
  slidesPerView: 1.2,
  loop: true,
  spaceBetween: 20,
  pagination: {
    el: ".swiper-custom-pagination",
    clickable: true,
  },
});
swiper.slideToLoop(1, 0);

You can also slide to the first slide (swiper.slideToLoop(0, 0);), tested and seems to work.

DrZivil commented 1 month ago

Same here, tried v9+, got the same results. So, downgraded to v8.4.7, works as expected.

Thanks! Worked for me too. (previously tried only V10 and V9)