Swiper v9 loop rewrite: slide sizing contract with slidesPerView 'auto' and centeredSlides after upgrading from v8
0 reputation · 01 Jun 2023, 10:09 UTC
0 reputation · 01 Jun 2023, 10:09 UTC
After migrating a carousel from Swiper 8 to Swiper 11, I am reworking a configuration that uses loop: true, slidesPerView: 'auto', and centeredSlides: true. Since v9 rearranges the real slide elements instead of cloning them, my old code that relied on duplicated slides and activeIndex no longer maps cleanly to what is rendered.
The slides have variable widths set in CSS, and the loop positioning now produces offsets that shift depending on when the CSS is applied relative to Swiper initialization. The migration guide documents realIndex versus activeIndex, but I cannot find a precise statement of the sizing contract Swiper expects for auto-width slides in loop mode — for example, whether widths must be fixed before init, whether loopAdditionalSlides interacts with variable widths, or whether margins on slides are included in the loop calculation.
slidesPerView: 'auto' is combined with loop mode in v9+?realIndex be used for all slide referencing after the v9 rewrite, and does it stay stable when slides are rearranged?update() or re-creating the loop after late-loading CSS the intended fix, or is there an init-time option that defers measurement?31275 reputation · 01 Jun 2023, 13:44 UTC
In Swiper v9 and later, the loop mechanism was rewritten to move away from simple cloning toward a more dynamic rearrangement of elements. When using slidesPerView: 'auto' and centeredSlides: true, Swiper calculates the transition offset based on the computed width of the slides at the moment of initialization.
For the loop to function without jumps or offsets, Swiper requires that slide dimensions are stable and available in the DOM before the internal loop calculations occur. The "contract" is as follows:
width or flex-basis) that does not rely on the Swiper container's internal calculations.margin-right (or spaceBetween) in its total offset calculations. If margins are applied inconsistently across slides, the loop center will shift.After the v9 rewrite, realIndex is the only stable reference for the actual data slide being viewed. Because the loop now rearranges elements to create the illusion of infinity, activeIndex refers to the position within the rendered DOM (including duplicates), which changes as the user swipes. Use realIndex for all logic tied to your data source; it remains stable regardless of the internal rearrangement.
If your CSS is loaded asynchronously or applied after Swiper initializes, the initial measurements will be wrong. The intended fix is to trigger a recalculation once the styles are active.
// After CSS is confirmed to be loaded
swiper.update();
While update() refreshes dimensions, if the loop structure itself was calculated with 0px widths, you may need to destroy and re-initialize the instance to ensure the loop duplicates are correctly positioned.
.swiper-slide-duplicate elements in the DevTools. Ensure their computed width exactly matches the original slides.loopedSlides is explicitly set. When using slidesPerView: 'auto', Swiper may not always guess the correct number of clones needed to fill the viewport, causing a gap during the loop transition.Diagnostic Question: Are you using a CSS-in-JS library or a framework (like Vue/React) where the slides are rendered before the styles are injected into the document head?
Use comments to ask for clarification. Post a solution as an answer.
31,275 reputation · 01 Jun 2023, 17:02 UTC
One clarification worth adding to the sizing-contract answer: calling swiper.update() after late-loading CSS recalculates slide sizes and snap positions, but it does not necessarily re-run the loop rearrangement that was computed from the stale measurements. If offsets still drift after update(), try explicitly rebuilding with swiper.loopDestroy() followed by swiper.loopCreate() and then update() — verify the exact method names against your installed version, since the loop API has shifted between v9 and v11.
Two related points for variable-width slides:
loopAdditionalSlides is a count, not a width. With uneven slide widths, a value that works for one end of the carousel can leave a gap at the other, so size it against your narrowest slides.observer: true / observeParents: true options can catch DOM/style mutations and trigger updates automatically — useful when CSS load timing is out of your control, though it adds MutationObserver overhead.Quick verification: log swiper.slides[i].getBoundingClientRect().width at init versus after styles settle; a mismatch confirms the measurement-timing cause.