Methods
Embla Carousel provides a set of methods that let you extend and control the carousel programmatically.
Usage
Methods require an initialized carousel instance. They remain accessible while the instance is active and are invalid after calling destroy.
Calling methods
In the following example, the slideNodes method is called and logged to the console as soon as the carousel has been initialized:
import EmblaCarousel from 'embla-carousel'
const wrapperNode = document.querySelector('.embla')const viewportNode = wrapperNode.querySelector('.embla__viewport')
const emblaApi = EmblaCarousel(viewportNode, { loop: true })
console.log(emblaApi.slideNodes())<div class="embla"> <div class="embla__viewport"> <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div></div>import React, { useEffect } from 'react'import useEmblaCarousel from 'embla-carousel-react'
export function EmblaCarousel() { const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true })
useEffect(() => { if (!emblaApi) return console.log(emblaApi.slideNodes()) }, [emblaApi])
return ( <div className="embla"> <div className="embla__viewport" ref={emblaRef}> <div className="embla__container"> <div className="embla__slide">Slide 1</div> <div className="embla__slide">Slide 2</div> <div className="embla__slide">Slide 3</div> </div> </div> </div> )}<script setup>import { watch } from 'vue'import useEmblaCarousel from 'embla-carousel-vue'
const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true })
watch( emblaApi, (api) => { if (!api) return console.log(api.slideNodes()) }, { immediate: true })</script>
<template> <div class="embla"> <div class="embla__viewport" ref="emblaRef"> <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div> </div></template>import { createEffect, on } from 'solid-js'import useEmblaCarousel from 'embla-carousel-solid'
export function EmblaCarousel() { const [emblaRef, emblaApi] = useEmblaCarousel(() => ({ loop: true }))
createEffect( on(emblaApi, (api) => { if (!api) return console.log(api.slideNodes()) }) )
return ( <div class="embla"> <div class="embla__viewport" ref={emblaRef}> <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div> </div> )}<script> import useEmblaCarousel from 'embla-carousel-svelte'
let options = { loop: true }
const onInit = (event) => { emblaApi = event.detail console.log(emblaApi.slideNodes()) }</script>
<div class="embla"> <div class="embla__viewport" on:emblainit={onInit} use:useEmblaCarousel={{ options }} > <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div></div>Note: Starting with Svelte 5, the on: event handlers have been
deprecated. However, on:emblainit will remain for backward
compatibility.
TypeScript
The EmblaCarouselType is obtained directly from the core package embla-carousel and used like so:
import EmblaCarousel, { EmblaCarouselType } from 'embla-carousel'
const wrapperNode = <HTMLElement>document.querySelector('.embla')const viewportNode = <HTMLElement>wrapperNode.querySelector('.embla__viewport')
const emblaApi = EmblaCarousel(viewportNode, { loop: true })
const logSelectedSnap = (emblaApi: EmblaCarouselType): void => { console.log(emblaApi.selectedSnap())}
emblaApi.on('select', logSelectedSnap)<div class="embla"> <div class="embla__viewport"> <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div></div>import React, { useEffect } from 'react'import { EmblaCarouselType } from 'embla-carousel'import useEmblaCarousel from 'embla-carousel-react'
export function EmblaCarousel() { const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true })
const logSelectedSnap = (emblaApi: EmblaCarouselType) => { console.log(emblaApi.selectedSnap()) }
useEffect(() => { if (!emblaApi) return emblaApi.on('select', logSelectedSnap) }, [emblaApi])
return ( <div className="embla"> <div className="embla__viewport" ref={emblaRef}> <div className="embla__container"> <div className="embla__slide">Slide 1</div> <div className="embla__slide">Slide 2</div> <div className="embla__slide">Slide 3</div> </div> </div> </div> )}If you're using pnpm, you need to install embla-carousel as a
devDependency when importing types from it like demonstrated above.
This is because even though embla-carousel-react has embla-carousel as
a dependency, pnpm makes nested dependencies inaccessible by design.
<script setup lang="ts">import { watch } from 'vue'import { EmblaCarouselType } from 'embla-carousel'import useEmblaCarousel from 'embla-carousel-vue'
const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true })
const logSelectedSnap = (emblaApi: EmblaCarouselType) => { console.log(emblaApi.selectedSnap())}
watch( emblaApi, (api) => { if (!api) return api.on('select', logSelectedSnap) }, { immediate: true })</script>
<template> <div class="embla"> <div class="embla__viewport" ref="emblaRef"> <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div> </div></template>If you're using pnpm, you need to install embla-carousel as a
devDependency when importing types from it like demonstrated above.
This is because even though embla-carousel-vue has embla-carousel as a
dependency, pnpm makes nested dependencies inaccessible by design.
import { createEffect, on } from 'solid-js'import { EmblaCarouselType } from 'embla-carousel'import useEmblaCarousel from 'embla-carousel-solid'
export function EmblaCarousel() { const [emblaRef, emblaApi] = useEmblaCarousel(() => ({ loop: true }))
const logSelectedSnap = (emblaApi: EmblaCarouselType) => { console.log(emblaApi.selectedSnap()) }
createEffect( on(emblaApi, (api) => { if (!api) return api.on('select', logSelectedSnap) }) )
return ( <div class="embla"> <div class="embla__viewport" ref={emblaRef}> <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div> </div> )}If you're using pnpm, you need to install embla-carousel as a
devDependency when importing types from it like demonstrated above.
This is because even though embla-carousel-solid has embla-carousel as
a dependency, pnpm makes nested dependencies inaccessible by design.
<script lang="ts"> import { EmblaCarouselType, EmblaOptionsType } from 'embla-carousel' import useEmblaCarousel from 'embla-carousel-svelte'
let emblaApi: EmblaCarouselType let options: EmblaOptionsType = { loop: true }
const logSelectedSnap = (emblaApi: EmblaCarouselType): void => { console.log(emblaApi.selectedSnap()) }
const onInit = (event: CustomEvent<EmblaCarouselType>): void => { emblaApi = event.detail emblaApi.on('select', logSelectedSnap) }</script>
<div class="embla"> <div class="embla__viewport" on:emblainit={onInit} use:useEmblaCarousel={{ options }} > <div class="embla__container"> <div class="embla__slide">Slide 1</div> <div class="embla__slide">Slide 2</div> <div class="embla__slide">Slide 3</div> </div> </div></div>Note: Starting with Svelte 5, the on: event handlers have been
deprecated. However, on:emblainit will remain for backward
compatibility.
If you're using pnpm, you need to install embla-carousel as a
devDependency when importing types from it like demonstrated above.
This is because even though embla-carousel-svelte has embla-carousel
as a dependency, pnpm makes nested dependencies inaccessible by design.
Reference
Below follows an exhaustive list of all Embla Carousel methods with their respective parameters and return values.
rootNode
noneHTMLElementemblaApi.rootNode()Get the root node that holds the scroll container with slides inside. This method can be useful when you need to manipulate the root element dynamically or similar.
containerNode
noneHTMLElementemblaApi.containerNode()Get the container node that holds the slides. This method can be useful when you need to manipulate the container element dynamically or similar.
slideNodes
noneHTMLElement[]emblaApi.slideNodes()Get all the slide nodes inside the container. This method can be useful when you need to manipulate the slide elements dynamically or similar.
goToNext
(instant?: boolean)voidemblaApi.goToNext(true | false)Scroll to the next scroll snap if possible. When loop is disabled and the carousel has reached the last scroll snap, this method won't do anything. Set the instant parameter to true when you want the scroll to happen instantly (no scroll animation).
goToPrev
(instant?: boolean)voidemblaApi.goToPrev(true | false)Scroll to the previous scroll snap if possible. When loop is disabled and the carousel has reached the first scroll snap, this method won't do anything. Set the instant parameter to true when you want the scroll to happen instantly (no scroll animation).
goTo
(index: number, instant?: boolean, direction?: 'forward' | 'backward')voidemblaApi.goTo(0, true | false, 'forward' | 'backward')Scroll to a scroll snap by its unique index. Set the instant parameter to true when you want the scroll to happen instantly (no scroll animation). If loop is enabled and the direction parameter is omitted, Embla Carousel will choose the closest way to the target scroll snap.
Note: A scroll snap isn't equivalent to a slide. A scroll snap can hold
multiple slides based on what options are set. For example, if
slidesToScroll is set to anything more than
1 or auto and multiple slides fit inside the viewport, a scroll snap will
hold multiple slides.
canGoToNext
nonebooleanemblaApi.canGoToNext()Check the possibility to scroll to the next scroll snap. If loop is enabled and the container holds any slides, this will always return true.
canGoToPrev
nonebooleanemblaApi.canGoToPrev()Check the possibility to scroll to the previous scroll snap. If loop is enabled and the container holds any slides, this will always return true.
selectedSnap
nonenumberemblaApi.selectedSnap()Get the index of the selected scroll snap. This method can be useful when you need to know which scroll snap is currently selected.
previousSnap
nonenumberemblaApi.previousSnap()Get the index of the previously selected scroll snap. This method can be useful when you need to know which scroll snap was previously selected.
snapList
nonenumber[]emblaApi.snapList()Returns an array of all scroll snap positions.
Each value represents the carousel's progress required to reach that position, where 0 is the start and 1 is the end (for example, 0.5 = 50% progress).
snapIndex
(offset: number)numberemblaApi.snapIndex(0)Get the selected scroll snap index. Provide a positive or negative offset to compute a different index (for example, 1 for the next snap or -1 for the previous snap).
ssrStyles
(container: string, slides?: string)stringemblaApi.ssrStyles('.embla__container', '.embla__slide')Generate CSS for server-side rendering (SSR). This helper outputs minimal styles for the specified container and slide selectors, ensuring a stable, non-shifting layout when rendered on the server. When called on a client-initialized instance, it returns an empty string. Wrap the output in a <style> tag.
Note: Make sure to choose a unique selector for your container to avoid affecting other Embla Carousels on the same page.
scrollProgress
nonenumberemblaApi.scrollProgress()Check how far the carousel has scrolled of its scrollable length from 0 - 1. For example, 0.5 equals 50%. For example, this can be useful when creating a scroll progress bar.
slidesInView
nonenumber[]emblaApi.slidesInView()Get slide indexes visible in the carousel viewport. Honors the inViewThreshold option.
cloneEngine
(options?: EmblaOptionsType)EmblaEngineTypeemblaApi.cloneEngine({ slidesToScroll: 'auto' })This method creates and returns a new Embla engine instance that acts as a passive copy of the original. The cloned engine has no event listeners attached, such as resize or slide change handlers.
You may optionally provide new options to override the existing configuration for the cloned instance. This is particularly useful when building plugins or handling more advanced use cases where a non-reactive engine is required.
Note: Please refrain from creating bug reports related to this method. If you're using this and running into problems, it's a 99.8% chance that you don't understand how this works. Use at your own risk.
internalEngine
noneEmblaEngineTypeemblaApi.internalEngine()Exposes most of Embla's internal functionality. This is primarily intended for plugin development or other advanced use cases where deeper access to the engine is required.
Note: Please refrain from creating bug reports related to this method. If you're using this and running into problems, it's a 99.8% chance that you don't understand how this works. Use at your own risk.
reInit
(options?: EmblaOptionsType, plugins?: EmblaPluginType[])voidemblaApi.reInit({ loop: false }, [Autoplay()])Hard reset the carousel after it has been initialized. This method allows for changing options and plugins after initializing a carousel.
Note: Passed options will be merged with current options, but passed plugins will replace current plugins.
plugins
noneEmblaPluginsTypeemblaApi.plugins()Returns an object with key value pairs where the keys are the plugin names, and the plugin API:s are the values.
destroy
nonevoidemblaApi.destroy()Destroy the carousel instance permanently. This is a one way operation and is intended to be used as a cleanup measure when the carousel instance isn't needed anymore.
on
(type: EventType, callback: EmblaEventCallbackType<EventType>)voidemblaApi.on('select', (emblaApi, event) => {})Subscribe to an Embla event with a callback. Added event listeners will persist even if reinit is called, either until the carousel is destroyed or the event is removed with the off method.
off
(type: EventType, callback: EmblaEventCallbackType<EventType>)voidemblaApi.off('select', (emblaApi, event) => {})Unsubscribe from an Embla event. Make sure to pass the same callback reference when the callback was added with the on method.
createEvent
(type: EventType, detail: EmblaEventListType[EventType])EmblaCreatedEventTypeemblaApi.createEvent('select', { targetSnap: 1, sourceSnap: 0 })Create an event object that can be emitted at a later time. This is useful if you want to trigger an event programmatically or build plugins. The returned object exposes an emit() method that will notify all registered listeners for the given event.