[Bug]: reInit() is called synchronously inside ResizeObserver callback

Author: AlecRustCreated Mar 30, 2026Updated Sep 2, 2026
Labelsbugcore

Which variants of Embla Carousel are you using?

  • embla-carousel (Core)
  • embla-carousel-react
  • embla-carousel-vue
  • embla-carousel-svelte
  • embla-carousel-autoplay
  • embla-carousel-auto-scroll
  • embla-carousel-solid
  • embla-carousel-auto-height
  • embla-carousel-class-names
  • embla-carousel-fade
  • embla-carousel-website (Documentation)

Steps to reproduce

  1. Create a standalone HTML page that uses [email protected] only, without any application code around it.
  2. Render a basic Embla carousel inside a wrapper element whose width can be toggled between two values, for example 1000px and 520px.
  3. Wrap window.ResizeObserver so you can track when its callback is active.
  4. Patch emblaApi.reInit() so you can count how many times it runs while the ResizeObserver callback is still active.
  5. Toggle the wrapper width several times.
  6. Log the counters.

In my isolated repro, the result is:

json
{
  "roCallbacks": 13,
  "reInitCalls": 6,
  "reInitInsideRO": 6
}

So Embla calls reInit() synchronously while the ResizeObserver callback is still running.

I then repeated the same repro with a custom watchResize override:

typescript
watchResize: (emblaApi) => {
  requestAnimationFrame(() => emblaApi.reInit())
  return false
}

That produced:

json
{
  "roCallbacks": 58,
  "reInitCalls": 58,
  "reInitInsideRO": 0
}

So deferring reInit() removes the problematic condition.

Expected Behavior

Embla should avoid calling reInit() synchronously from inside the ResizeObserver callback.

The resize handling should move the reInit() work out of the observer callback, for example by deferring it with requestAnimationFrame, so responsive layouts do not hit ResizeObserver loop warnings.

Additional Context

I isolated this outside my app in a standalone Embla-only page, so this does not appear to depend on framework integration or application-specific code.

The reason I’m reporting this as a library bug is that the current source still appears to call reInit() directly from the default resize path:

https://github.com/davidjerleke/embla-carousel/blob/master/packages/embla-carousel/src/components/ResizeHandler.ts

This also looks related to the earlier ResizeObserver fix in:

That earlier fix deferred resize-triggered reInit() with requestAnimationFrame, which matches what I see in the isolated repro: once reInit() is deferred, it no longer runs inside the ResizeObserver callback.

The browser warning itself may be timing-sensitive, but the underlying behaviour is deterministic and verifiable: in the standalone repro, reInit() is called from inside the active ResizeObserver callback with default Embla behaviour, and no longer is once reInit() is deferred.

What browsers are you seeing the problem on?

Chrome

Version

v8.6.0

CodeSandbox

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

Before submitting

  • I've made research efforts and searched the documentation
  • I've searched for existing issues
  • I agree to follow this project's Contributing Guidelines for bug reports

Source: davidjerleke/embla-carousel