Swiper: Resizing on container resize instead of window resize

Created on 8 Dec 2020  路  5Comments  路  Source: nolimits4web/swiper

This is a:

  • [ ] bug
  • [x] enhancement
  • [x] feature-discussion (RFC)

I'd like to suggest implementing the ResizeObserver API as proposed years ago in #2068 .

Browser support is now more widespread and this would really help in cases where CSS is loaded asynchronously ("non-critical"). Consider for instance this situation:

  • browser loads critical CSS and performs first paint
  • browser loads ES modules (swiper)
  • swiper.init()
  • async CSS is loaded that changes the size of .swiper-container

One reason to NOT implement the ResizeObserver API would be that if the slider is shown above-the-fold, then all .swiper-container's style should already be loaded and therefore there would be no problem. Otherwise, i.e. swiper loaded "below-the-fold", then lazy initialize it using IntersectionObserver as even async styles are likely to have been loaded at this point.

However, consider this case:

  • browser loads critical CSS and performs first paint
  • browser loads swiper via ES modules (deferred)
  • user scrolls
  • .swiper-container becomes visibile and swiper is initialized via IntersectionObserver
  • async "below-the-fold" CSS is loaded and resizes .swiper-container

This clearly breaks proper slide sizing which uses Swiper's internal methods updateSize() and updateSlides().

feature request

Most helpful comment

This is what I've come up with so far:

const ResizeObserver = {
    name: 'resize',
    create: (swiper: Swiper) => {
        Object.assign(swiper, {
            resizeObserver: null
        });
    },
    on: {
        init: (swiper: Swiper) => {
            const container = swiper.$el[0]
            console.debug(`Swiper.resizeObserver.init container=`, container);

            if (!('ResizeObserver' in window)) return;

            const observer = new ResizeObserver((entries) => {
                console.debug(entries);
                swiper.emit('observerUpdate');
            });

            observer.observe(container, {box: 'border-box'});

            swiper.resizeObserver = observer;
        }
    },
    destroy: (swiper: Swiper) => {
        console.debug(`Swiper.resizeObserver.destroy`);

        if (swiper.resizeObserver) {
            swiper.resizeObserver.disconnect();
        }
    }
} as SwiperComponent;

Use with Swiper.use([ResizeObserver]) and updateOnWindowResize: false.

It leverages events from the MutationObserver module (observer.js) to trigger onResize core handler.

I would go as far as saying that this should be integrated in modules/resize/resize.js as a replacement for window's resize event when ResizeObserver is available.

All 5 comments

This is what I've come up with so far:

const ResizeObserver = {
    name: 'resize',
    create: (swiper: Swiper) => {
        Object.assign(swiper, {
            resizeObserver: null
        });
    },
    on: {
        init: (swiper: Swiper) => {
            const container = swiper.$el[0]
            console.debug(`Swiper.resizeObserver.init container=`, container);

            if (!('ResizeObserver' in window)) return;

            const observer = new ResizeObserver((entries) => {
                console.debug(entries);
                swiper.emit('observerUpdate');
            });

            observer.observe(container, {box: 'border-box'});

            swiper.resizeObserver = observer;
        }
    },
    destroy: (swiper: Swiper) => {
        console.debug(`Swiper.resizeObserver.destroy`);

        if (swiper.resizeObserver) {
            swiper.resizeObserver.disconnect();
        }
    }
} as SwiperComponent;

Use with Swiper.use([ResizeObserver]) and updateOnWindowResize: false.

It leverages events from the MutationObserver module (observer.js) to trigger onResize core handler.

I would go as far as saying that this should be integrated in modules/resize/resize.js as a replacement for window's resize event when ResizeObserver is available.

I've just tested v6.5.0 and resizing the viewport does not update swiper. I haven't had time to further investigate the issue, but for now I'm reverting to using my module.

If issue persists, please provide a live example/fiddle with the issue

I figured it out: in order for resizeObserver to work on .swiper-container, updateOnWindowResize must be set to true. I believe this should at the very least be mentioned in the docs.

Does enabling updateOnWindowResize result in the window.addEventListener('resize', ..) handler to be registered too? If so, the user should be given the option to disable the resize event listener thus use only ResizeObserver on the container for obvious performance reasons.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

callumacrae picture callumacrae  路  3Comments

leone510es picture leone510es  路  3Comments

danielcpereira11 picture danielcpereira11  路  4Comments

joakimk picture joakimk  路  3Comments

TomDeSmet picture TomDeSmet  路  3Comments