Draggable & Touch-friendly Carousel In Vanilla JavaScript – embla-carousel

Category: Javascript , Recommended , Slider | July 19, 2024
Views Total:7 views
Official Page:Go to website
Last Update:July 19, 2024


Draggable & Touch-friendly Carousel In Vanilla JavaScript – embla-carousel


The embla-carousel JavaScript library which helps developers to create a responsive, customizable, mobile-friendly carousel component on the web app.

Fully responsive based on CSS flexbox.

How to use it:

1. Install & download the package.

# Yarn
$ yarn add embla-carousel
$ npm install embla-carousel --save

2. Import the embla-carousel.

import EmblaCarousel from 'embla-carousel'

3. Or load the compiled JavaScript in the document.

<script src="https://unpkg.com/embla-carousel"></script>

4. Add slides to the embla carousel.

<div class="embla" id="embla">
  <div class="embla__container">
    <div class="embla__slide">
      Slide 1
    <div class="embla__slide">
      Slide 2
    <div class="embla__slide">
      Slide 3

5. Initialize the embla carousel.

const embla = EmblaCarousel(document.getElementById('embla'))

6. The basic CSS styles for the embla carousel.

.embla {
  overflow: hidden;
.embla__container {
  display: flex;
  will-change: transform;
.embla__slide {
  position: relative;
  flex: 0 0 auto;
  width: 100%;

7. Declare different options for different breakpoints.

.embla:before {
  display: none;
  content: '{
    "slidesToScroll": 1,
    "draggable": true
@media (min-width: 768px) {
  .embla:before {
    content: '{
      "slidesToScroll": 2,
      "draggable": false

8. Available options to customize the embla carousel.

const embla = EmblaCarousel(document.getElementById('embla'),{
      // activate or deactivate the carousel
      active: true,
      // or start, center,end, number
      align: 'center',
      // or 'y'
      axis: 'x',
      // an object with options that will be applied for a given breakpoint by overriding the options at the root level
      breakpoints: {},
      // Enables choosing a custom container element which holds the slides. By default, Embla will choose the first direct child element of the root element. 
      // Provide either a valid CSS selector string or a
      container: null,
      // choose between keeping redundant snap points or trimming them
      // 'trimSnaps' or 'keepSnaps'
      containScroll: '',
      // Enables using custom slide elements. By default, Embla will choose all direct child elements of its container. 
      // Provide either a valid CSS selector string or a nodeList/array containing HTML elements.
      slides: null,
      // the number of slides to show per page
      slidesToScroll: 1,
      // contains slides to the carousel viewport to prevent excessive scrolling at the beginning or the end
      containScroll: false,
      // enable draggable
      dragFree: false,
      dragThreshold: 10
      // auto spacing
      autoSpacing: false,
      // auto resize
      autoResize: false,
      // infinite loop
      loop: false,
      // animation speed
      speed: 10,
      // scroll duration when triggered by any of the API methods
      duration: 25,
      // start index
      // 0 = slide 1
      startIndex: 0,
      // scroll the carousel with mouse and touch interactions
      watchDrag: true,
      // watch the container and slides for size changes and run reInit when any size has changed
      watchResize: true,
      // watch the container for added and/or removed slides and run reInit if needed
      watchSlides: true
      // or using dir="rtl" on the top container
      direction: 'rtl',
      // allow the carousel to skip scroll snaps if it's dragged vigorously. 
      // Note that this option will be ignored if the dragFree option is set to true.
      skipSnaps: false,
      // choose a fraction representing the percentage portion of a slide that needs to be visible in order to be considered in view. 
      // For example, 0.5 equals 50%.
      inViewThreshold: 0,

9. Available API methods that can be used for creating your own carousel controls.

// gets the root node
// gets the container node
// returns an array of slide nodes
// goes to the next slide with or without scroll snap
// set the jump parameter to true when you want to go to the next slide instantly.
// goes to the previous slide with or without scroll snap
// goes to a specific slide with or without scroll snap
embla.scrollTo(index: number, jump)
// checks if has previous slide
// checks if has next slide
// gets the current slide
// returns an array of numbers representing the scroll progress for each snap point
// gets the previous slide
// gets an array containing all the snap point positions
// gets the current scroll progress
// get slide indexes visible in the carousel viewport. Honors the inViewThreshold option
// set the target parameter to true when you want to get the slides visible at the scroll destination instead of the current scroll location.
// get slide indexes not visible in the carousel viewport. Honors the inViewThreshold option. 
// expose almost all internal functionality used by Embl
// re-init with new options
embla.reInit(options: options)
// returns an object with key value pairs where the keys are the plugin names, and the plugin API:s are the values
// destroys the instance
// event: EmblaEventType, callback: (emblaApi: EmblaCarouselType, eventName: EmblaEventType) => void
// event: EmblaEventType, callback: (emblaApi: EmblaCarouselType, eventName: EmblaEventType) => void
// event: EmblaEventType

10. Event handlers.

embla.on('init', function(e){
  // on init
embla.on('reinit', function(e){
  // on re-init
embla.on('destroy', function(e){
  // on destroy
embla.on('select', function(e){
  // on a slide selected
embla.on('scroll', function(e){
  // on scroll
embla.on('settle', function(e){
  // when the carousel has settled after scroll has been triggered
embla.on('resize', function(e){
  // on carousel resize
embla.on('slidesInView', function(e){
  // when any slide has entered or exited the viewport
embla.on('pointerDown', function(e){
  // on dragStart
embla.on('pointerUp', function(e){
  // on dragEnd
embla.on('slidesChanged', function(e){
  // when slides are added to, or removed from the carousel container

11. Enable the AUTOPLAY plugin.

$ npm i embla-carousel-autoplay
<!-- OR -->
<script src="https://unpkg.com/embla-carousel-autoplay/embla-carousel-autoplay.umd.js"></script>
const options = { /* OPTIONS */ }
const rootNode = (emblaRoot) => emblaRoot.parentElement
const autoplay = Autoplay(options, rootNode)
// Autoplay options
delay: 4000,
stopOnInteraction: true,
jump: false,
stopOnMouseEnter: false,
stopOnLastSnap: false,
// Autoplay methods

12. Enable the Auto Height plugin.

$ npm i embla-carousel-auto-height
<!-- OR -->
<script src="https://unpkg.com/embla-carousel-auto-height/embla-carousel-auto-height.umd.js"></script>
import EmblaCarousel from 'embla-carousel'
import AutoHeight from 'embla-carousel-auto-height'
const options = { 
  destroyHeight: 'auto' 
const embla = EmblaCarousel(emblaRoot, { 
  loop: false 
}, [AutoHeight(options)])

13. Enable the Class Names plugin.

$ npm i embla-carousel-class-names
<!-- OR -->
<script src="https://unpkg.com/embla-carousel-class-names/embla-carousel-class-names.umd.js"></script>
import EmblaCarousel from 'embla-carousel'
import ClassNames from 'embla-carousel-class-names'
const options = { 
  selected: 'is-selected',
  draggable: 'is-draggable',
  dragging: 'is-dragging'
const embla = EmblaCarousel(emblaRoot, { 
  loop: false }, [ClassNames(options)]

14. Enable the Wheel Gestures plugin.

$ npm i eembla-carousel-wheel-gestures/pre>
<!-- OR -->
<script src="https://unpkg.com/embla-carousel-wheel-gestures/embla-carousel-wheel-gestures.umd.js"></script>
import EmblaCarousel from 'embla-carousel'
import { WheelGesturesPlugin } from 'embla-carousel-wheel-gestures'
const wheelGestures = WheelGesturesPlugin({
  wheelDraggingClass: 'is-wheel-dragging',
  forceWheelAxis: undefined, // Choose scroll axis between x and y
const embla = EmblaCarousel(emblaRoot, { 
  loop: false }, [wheelGestures]

15. Enable the Auto Scroll plugin.

$ npm i embla-carousel-fade
<!-- OR -->
<script src="https://unpkg.com/embla-carousel-fade/embla-carousel-fade.umd.js"></script>
import EmblaCarousel from 'embla-carousel'
import AutoScroll from 'embla-carousel-auto-height'
const options = { 
  speed: 2,
  startDelay: 1000,
  direction: "forward", // or 'backward'
  playOnInit: true,
  stopOnInteraction: true,
  stopOnMouseEnter: false,
  stopOnFocusIn: true,
  rootNode: true,
const embla = EmblaCarousel(emblaRoot, { 
  loop: false 
}, [AutoScroll(options)])
//  Auto Scroll methods
//  Auto Scroll events
embla.on('autoScroll:play', function(e){
  // ...
embla.on('autoScroll:stop', function(e){
  // ...

16. Enable the Fade plugin.

$ npm i embla-carousel-fade
<!-- OR -->
<script src="https://unpkg.com/embla-carousel-fade/embla-carousel-fade.umd.js"></script>

17. Set global options.

  // options here


v8.1.7 (07/19/2024)

  • refactor(vue): optimize reactivity handling and reduce bundle size
  • [Bug]: Add interpolation to fixed time step to improve animation smoothness

v8.1.6 (07/01/2024)

  • Remove animation offset location

v8.1.5 (06/12/2024)

  • Add nodenext compatibility for ESM imports

v8.1.4 (06/11/2024)

  • [Bug]: Slide hanging if overdragged/scrolled
  • [Feat]: Add TypeScript moduleResolution: bundler support

v8.1.3 (05/20/2024)

  • Fixed for fade plugin

v8.1.2 (05/19/2024)

  • Bugfix

v8.1.1 (05/17/2024)

  • Add a fade plugin
  • Add slideFocus event

v8.0.4 (05/04/2024)

  • Add robust pinch zoom support

v8.0.2 (04/10/2024)

  • Bugfixes

v8.0.1 (04/03/2024)

  • Bugfixes

v8.0.0 (02/22/2024)

  • Automatic slide/container size change detection with ResizeObserver.
  • Automatic detection of added/removed slides with MutationObserver.
  • Improved performance of slidesInView now using IntersectionObserver instead of custom calculations.
  • New options to give devs more control: watchDrag, watchResize and watchSlides, dragThreshold.
  • New events: slidesChanged and slidesInView.
  • New Autoplay events: autoplay:play and autoplay:stop.
  • Embla now works with elements that come from other realms, such as iframes.
  • Support using tab on focusable elements to navigate the carousel.
  • Calculations for element dimensions and snap positions now work even if these elements have applied transforms.
  • Frame rate agnostic animations.
  • Support for any media queries (not just width queries) in breakpoints option.
  • New plugin: AutoScroll.
  • New integrations/wrappers
  • And more…

v7.1.0 (03/09/2023)

  • Add slides & container options.

v7.0.9 (01/24/2023)

  • Fixed Dragging not working well in Firefox for desktop.

v7.0.8 (01/22/2023)

  • Handle click prevention on drag automatically.

v7.0.7 (01/21/2023)

  • Bugfix
  • Passive event listeners

v7.0.5 (11/08/2022)

  • Bugfix

v7.0.4 (10/29/2022)

  • Bugfix

v7.0.3 (09/13/2022)

  • Bugfix

v7.0.2 (08/31/2022)

  • Added Autoplay jump parameter

v7.0.1 (08/18/2022)

  • Bugfixes

v7.0.0 (08/04/2022)

  • Breakpoints option
  • Expose plugin API:s from the Embla API
  • Active option
  • New option value: slidesToScroll: auto
  • React 18 Support
  • Vue 3 wrapper
  • Svelte wrapper
  • containScroll: Account for edge spacing
  • The transform unit has changed from % to px. As a result, the position: relative style on the slides needed for loop carousels to work is not necessary anymore.
  • Bugfix: Non-visible slides when using CSS grid in combination with loop: true
  • Bugfix: Embla + Framer Motion + Flubber makes slides “disappear”
  • Expose plugin API:s from the Embla API

v6.2.0 (02/07/2022)

  • Adds the ability to set global options

v6.1.1 (01/20/2022)

  • Bugfixes

v6.1.0 (01/16/2022)

  • Adds the Auto Height plugin to NPM.

v6.0.2 (11/22/2021)

  • Adds the Class Name plugin

v6.0.1 (11/09/2021)

  • Bugfix

v6.0.0 (11/06/2021)

  • New Plugin system
  • Dropping IE11 support
  • Added Autoplay plugin

v4.5.3 (05/24/2021)

  • Fixes the broken type declarations for the useEmblaCarousel hook that was introduced in v4.5.2

v4.5.2 (05/23/2021)

  • Update

v4.5.1 (04/28/2021)

  • Improvements

v4.5.0 (04/22/2021)

  • With this release, it’s possible to turn off the behavior where the carousel skips scroll snaps when it’s dragged vigorously. This will be an opt-in option for now, but with the next major release (v.5), this will be the default behavior.

v4.4.1 (04/21/2021)

  • Update package

v4.4.0 (04/11/2021)

  • With this release, it’s possible to scroll instantly to a scroll snap with the jump parameter. It’s a boolean and default is false. The following methods accept the jump parameter: scrollTo, scrollNext, and scrollPrev

v4.3.2 (04/05/2021)

  • Fixed Error when scrolling between slides by dragging

v4.3.1 (04/02/2021)

  • Fixed Breakpoint options not reset

v4.3.0 (03/22/2021)

  • Allows you to declare different options for different breakpoints. It’s achieved by using the content attribute of the pseudo-element :before on the root node.

v4.2.1 (03/17/2021)

  • Removes the transform rounding in the Translate component.

v4.2.0 (03/12/2021)

  • Auto Spacing Detection
  • AutoResize Option
  • Root Node Method
  • Bugfixes

v4.1.3 (01/06/2021)

  • This release comes with a refactored eventEmitter component that slightly reduces the bundle size.

v4.1.2 (12/07/2020)

  • The ScrollBounds component is now responsible for applying friction instead of the dragHandler component when the carousel is out of bounds.

v4.1.1 (11/25/2020)

  • Update

v4.1.0 (11/12/2020)

  • Added RTL Support

v4.0.6 (10/20/2020)

  • Remove exposure of location from scrollBody and rename default named methods to base

v4.0.5 (09/30/2020)

  • Check for truthy class names before toggling them

v4.0.4 (09/20/2020)

  • Bugfixes

v4.0.3 (09/13/2020)

  • Bugfixes

v4.0.2 (09/09/2020)

  • Resize debounce bugfix

v3.0.28 (08/22/2020)

  • Mark package as side effect free

v3.0.27 (08/20/2020)

  • A fix for the window bind issue has been merged
  • The drag handler now respects event.cancelable and bails if it returns false

v3.0.26 (08/14/2020)

  • Bug fix

v3.0.25 (08/13/2020)

  • Small code improvements that resulted in smaller bundle size.

v3.0.25 (08/11/2020)

  • Remove unnecessary declarations

v3.0.23 (08/02/2020)

  • Bugfixes

v3.0.20 (07/22/2020)

  • Add Type suffix to exported types

v3.0.19 (07/20/2020)

  • React dependency issue fix

v3.0.17 (07/10/2020)

  • Fixed: Type definition file refers to files that don’t exist in the build

v3.0.10 (06/27/2020)

  • Added React component.

v3.0.0 (06/12/2020)

  • New options.
  • dragStart has been renamed to pointerDown.
  • dragEnd has been renamed to pointerUp.
  • scrollBy() has been removed.
  • scrollToProgress() has been removed.
  • target : boolean for the API method scrollProgress() has been removed.
  • changeOptions() has been renamed to reInit().
  • scrollSnapList() now returns an array of numbers representing the scroll progress for each snap point. Indexes and slide nodes per snap point has been removed.
  • Bugs fixed.

v2.9.1 (04/22/2020)

  • Added scrollToProgress method

v2.9.0 (03/27/2020)

  • Added a new feature which allows users to specify percentage alignment by passing a number, where a fraction like 0.2 represents 20% of the viewport size. Percentage will be measured from the start edge of the viewport.

v2.8.0 (02/26/2020)

  • Added Settle event

v2.7.4 (02/13/2020)

  • Fixed Android touch device event bug

v2.7.0 (01/31/2020)

  • Added new scrollBy() method.

v2.6.4 (12/05/2019)

  • Bugfixes

v2.6.0 (11/15/2019)

  • Added clickAllowed() method.

v2.5.5 (11/09/2019)

  • Package updates

v2.5.0 (10/07/2019)

  • Added scrollProgress method.

v2.4.0 (08/31/2019)

  • When using the option containScroll Embla will automatically merge any excessive snap points that share the same snap position

v2.3.0 (07/16/2019)

  • Added ‘scroll’ event.

v2.2.0 (07/11/2019)

  • Added on click API Method

v2.1.14 (07/11/2019)

  • Fixed canScrollNext & canScrollPrev bug

v2.1.13 (07/10/2019)

  • Updated

v2.1.10 (07/06/2019)

  • New containScroll options

v2.0.3 (07/04/2019)

  • Solved the Webpack 4 UMD module window issue.

v2.0.0 (06/25/2019)

  • Improved drag accuracy
  • Improved link handling
  • More API methods added
  • Changed API method names
  • Removed groupedIndexes() method

v1.0.0 (06/19/2019)

  • groupSlides –> slidesToScroll
  • hasPreviousIndex() –> canScrollPrevious()
  • hasNextIndex() –> canScrollNext()

v0.9.0 (06/16/2019)

  • Added more API.

v0.8.0 (06/13/2019)

  • Add: closeOnScroll option to close pickr if the user scrolls the area behind it. Useful on nested scrollable elements.
  • Change: Make pickr’s position absolute to prevent sticking at the top.
  • Change: Make swatches not-centered

v0.7.2 (06/08/2019)

  • Drag threshold has been lowered. Less drag force is now required for a slide change to occur.

You Might Be Interested In:

Leave a Reply