5

I'm building a thumbnail gallery with a slider feature using Swiper (v6.5.1). By default, the slider is hidden, and when the user clicks one of the images, the slider must be displayed showing the clicked image. Once the slider is open, the user can click a Close button to hide it and return to the thumbnail gallery.

This is the code I'm using:

JS:

var swiper;

swiper = new Swiper( '.gallery-slider .swiper-container', {
    loop: true,
    observer: true,
    observeParents: true,
    autoplay: {
        delay: 3000,
        disableOnInteraction: false,
    },
    navigation: {
        nextEl: '.swiper-next',
        prevEl: '.swiper-prev',
    },
});

document.querySelectorAll( '.gallery-thumbnails a[data-slide]' ).forEach( item => {
    item.addEventListener( 'click', function( e ) {
        e.preventDefault();
        window.scrollTo( 0, 0 );
        document.querySelector( '.gallery-thumbnails' ).style.display = 'none';
        document.querySelector( '.gallery-slider .swiper-container' ).style.display = 'block';
        var slideno = $( this ).data( 'slide' );
        swiper.slideTo( slideno + 1, false, false );
    });
});

document.querySelector( '.gallery-slider .close' ).addEventListener( 'click', function( e ) {
    e.preventDefault();
    document.querySelector( '.gallery-slider .swiper-container' ).style.display = 'none';
    document.querySelector( '.gallery-thumbnails' ).style.display = 'flex';
});

CSS:

.gallery-slider .swiper-container {
    display: none;
}

HTML:

<div class="gallery-thumbnails">
    <div class="gallery-image"><a href="" data-slide="0"><img src="thumb0.jpg" /></a></div>
    <div class="gallery-image"><a href="" data-slide="1"><img src="thumb1.jpg" /></a></div>
    <div class="gallery-image"><a href="" data-slide="2"><img src="thumb2.jpg" /></a></div>
    <div class="gallery-image"><a href="" data-slide="3"><img src="thumb3.jpg" /></a></div>
    ....
</div>

<div class="gallery-slider">
    <div class="swiper-container">
        <div class="swiper-prev">previous</div>
        <div class="swiper-next">next</div>
        <div class="close">close</div>
        <div class="swiper-wrapper">
            <div class="swiper-slide"><img src="slide0.jpg" /></div>
            <div class="swiper-slide"><img src="slide1.jpg" /></div>
            <div class="swiper-slide"><img src="slide2.jpg" /></div>
            <div class="swiper-slide"><img src="slide3.jpg" /></div>
            ....
        </div>
    </div>
</div>

As you can see, the code uses Swiper's observer feature, which reinitializes Swiper each time there's a change in its style (like hide/show) or in its child elements (like adding/removing slides).

Everything works as expected the first time I click an image in the thumbnail gallery. But, if I hide the slider using the Close button and then click in a new image to open the slider again, the slider appears but is not responsive until some seconds have passed. The strange thing is that this delay is not always the same. Sometimes is almost instantaneous and sometimes more than x seconds have already passed when the slider begins to respond to clicks in the next and previous buttons. One thing I noticed is that if I resize the window, the slider becomes responsive instantly.

I tried this code in the latest Chrome and Firefox with the same results.

Is this the expected behavior? Is the MutationObserver used by the observer feature not always listening to changes in the DOM? Am I initializing Swiper the wrong way?

This is the code for the Swiper observer:

https://github.com/nolimits4web/swiper/blob/master/src/modules/observer/observer.js

2
  • Just curious, what is the performance impact of setting the display to hidden instead of none. There is method to this madness as the DOM essentially kills the nodes when you use display: none, having to build these again when display is set back to a visible state (flex in this case). Meaning the re-rendering might be the bottleneck here. On resize they exist already, so this is fast. This seems inline with obeservations.
    – Daniel ZA
    Commented Apr 6, 2021 at 6:44
  • Using visibility: hidden instead of display: none makes no difference in result. The delay is still there when setting the visibility prop to visible.
    – leemon
    Commented Apr 29, 2021 at 7:45

1 Answer 1

0

I found the culprit of the strange delay. I was passing a boolean as the second argument in the slideTo function instead of an integer, which is the correct type for it.

You must change the line:

swiper.slideTo( slideno + 1, false, false );

to:

swiper.slideTo( slideno + 1, 0, false );
2
  • 1
    Awesome, it is uncanny that it would cause a performance impact as bool get parsed to integer without issue if unless strict comparisons are made. But then again we can't see the internals of the Swiper class, so just glad you got it solved.
    – Daniel ZA
    Commented Apr 30, 2021 at 8:37
  • 1
    Yep, the slideTo() function does a strict comparison using the second arg.
    – leemon
    Commented Apr 30, 2021 at 22:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.