How Embla Carousel Works

Embla Carousel uses minimal DOM manipulation to deliver smooth, high-performance scrolling.


Minimal DOM manipulation

Embla changes the DOM in only two ways:

  • Carousel container - applies translate3d to create the scroll effect.
  • Carousel slides - applies translate3d to adjust slide positions (for looping) and improve scroll performance.

You can see this in action by inspecting the following example in your browser's developer tools:

The container receives an inline transform:

<div class="embla">  <div class="embla__viewport">    <div      class="embla__container"      style="transform: translate3d(73.5px, 0px, 0px)"    >      <!-- slides -->    </div>  </div></div>

And slides may also receive inline transform styles:

<div class="embla__slide" style="transform: translate3d(0px, 0px, 0px)">  <div class="embla__slide__number">    <span>1</span>  </div></div><div class="embla__slide" style="transform: translate3d(0px, 0px, 0px)">  <div class="embla__slide__number">    <span>2</span>  </div></div>
<!-- ...and so on -->

That's it — nothing else is added to the DOM. Embla does not encapsulate or wrap any elements, so you retain full control over your markup, structure, and styling. This behavior applies to the core library as well as the official framework wrappers. Plugins, however, may modify the DOM further, so check individual plugin pages for details.

Notes

Before adding custom styles, remember how Embla manipulates the DOM — applying styles incorrectly can break its functionality.

Warning: Do not apply custom transform or transition styles directly to the carousel container or slides. Embla applies transforms via inline styles and animates them using a spring-based system with requestAnimationFrame; adding your own will conflict and break the carousel's behavior.

Instead, apply transforms/transitions to a wrapper element around the carousel:

<div  class="embla"  style="transform: scale(0.9); transition: transform 0.3s ease">  <div class="embla__viewport">    <div class="embla__container">      <!-- slides -->    </div>  </div></div>

When applying transforms/transitions to slides, create an inner element within each slide:

<div class="embla__slide">  <div    class="embla__slide__inner"    style="transform: rotate(5deg); transition: transform 0.3s ease"  >    <!-- slide content -->  </div></div>

This approach keeps Embla's animations intact while giving you full flexibility to style and animate around them.

Edit this page on GitHub