This documentation is for v9.0.0-rc04. While v9 is currently in RC, it can be considered stable as several known bugs from previous versions have been fixed.
If you still prefer to use the latest stable release, see the v8 documentation .
If you still prefer to use the latest stable release, see the v8 documentation .
Required Setup
Embla Carousel works by controlling a scrollable container within a viewport element. To get started, you'll need a minimal HTML and CSS setup.
Prerequisites
Before continuing with this guide, make sure you've completed the following:
Core structure
Your markup must follow this pattern:
- An overflow wrapper (
embla__viewportbelow) that hides overflowing content. - A scroll container (
embla__container) that holds and scrolls the slides. - One or more slides (
embla__slide). Embla also supports an empty state with no slides.
Base CSS
.embla__viewport { overflow: hidden;}
.embla__container { display: flex; touch-action: pan-y pinch-zoom;}
.embla__slide { flex: 0 0 100%; min-width: 0;}.embla__viewport { overflow: hidden;}
.embla__container { display: flex; touch-action: pan-y pinch-zoom;}
.embla__slide { flex: 0 0 100%; min-width: 0;}<style scoped>.embla__viewport { overflow: hidden;}
.embla__container { display: flex; touch-action: pan-y pinch-zoom;}
.embla__slide { flex: 0 0 100%; min-width: 0;}</style>.embla__viewport { overflow: hidden;}
.embla__container { display: flex; touch-action: pan-y pinch-zoom;}
.embla__slide { flex: 0 0 100%; min-width: 0;}<style> .embla__viewport { overflow: hidden; }
.embla__container { display: flex; touch-action: pan-y pinch-zoom; }
.embla__slide { flex: 0 0 100%; min-width: 0; }</style>Markup and script
import EmblaCarousel from 'embla-carousel'
const wrapperNode = document.querySelector('.embla')const viewportNode = wrapperNode.querySelector('.embla__viewport')const emblaApi = EmblaCarousel(viewportNode)<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>
<!-- Optional: Add navigation controls here --></div>import React from 'react'import useEmblaCarousel from 'embla-carousel-react'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel()
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>
{/* Optional: Add navigation controls here */} </div> )}<script setup>import useEmblaCarousel from 'embla-carousel-vue'
const [emblaRef] = useEmblaCarousel()</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>
<!-- Optional: Add navigation controls here --> </div></template>import useEmblaCarousel from 'embla-carousel-solid'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel()
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>
{/* Optional: Add navigation controls here */} </div> )}<script> import useEmblaCarousel from 'embla-carousel-svelte'</script>
<div class="embla"> <div class="embla__viewport" use:useEmblaCarousel> <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>
<!-- Optional: Add navigation controls here --></div>Notes
- Class names are just examples — use any naming scheme you prefer, as long as the HTML structure and CSS rules stay the same.
- You can use other semantic elements instead of
<div>(e.g.<section>,<article>). - The example uses flexbox for horizontal slides, but CSS Grid or other layout methods also work.
flex: 0 0 100%makes each slide take up the full carousel width. Adjust this for multi-slide layouts or custom designs.- The outer
.emblawrapper shown in the examples is optional. You can use it as a convenient container for navigation controls or styling, but Embla only requires the viewport → container → slides hierarchy.
Important: The overflow: hidden on the viewport element is mandatory.
Without it, slides will overflow outside the viewport and Embla cannot guarantee
correct scrolling behavior.