Grouping Slides
This guide shows you how to group multiple slides so they behave as a single slide in Embla Carousel.
Prerequisites
Before continuing with this guide, make sure you've completed the following:
Understanding grouping
Grouping slides changes how the carousel measures and snaps — instead of treating each slide individually, Embla treats each group of slides as one scroll unit (slide). This is especially useful when building multi-slide layouts (multiple slides visible per view) and when you want to scroll several slides at once, creating a paged scrolling effect.
Tip: Grouping slides doesn't visually combine them — it only changes how Embla calculates snapping and scroll distances. You can still size and space slides freely using your CSS.
Setting groups
You can configure the grouping using the slidesToScroll option:
import EmblaCarousel from 'embla-carousel'
const wrapperNode = document.querySelector('.embla')const viewportNode = wrapperNode.querySelector('.embla__viewport')const emblaApi = EmblaCarousel(viewportNode, { slidesToScroll: 2})<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 from 'react'import useEmblaCarousel from 'embla-carousel-react'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel({ slidesToScroll: 2 })
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 useEmblaCarousel from 'embla-carousel-vue'
const [emblaRef] = useEmblaCarousel({ slidesToScroll: 2 })</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 useEmblaCarousel from 'embla-carousel-solid'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel(() => ({ slidesToScroll: 2 }))
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 = { slidesToScroll: 2 }</script>
<div class="embla"> <div class="embla__viewport" 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>Take a look at the snap count in the bottom-right corner of the example — it updates when you change the slidesToScroll option.
That's because Embla recalculates the number of snap points based on how slides are grouped.
The slidesToScroll option defines how many slides move per scroll:
auto— Automatically groups slides based on how many fit inside the viewport, using each slide's computed size. This means the grouping adapts automatically to responsive layouts — each scroll moves one “page” of visible slides until the end of the list.number(default:1) — Moves the specified number of slides per scroll, regardless of their size or how many fit in view.
Breakpoints
You can make carousel grouping responsive by setting different slidesToScroll values for specific viewport sizes using the breakpoints option.
Embla automatically recalculates slide groups and snap positions when breakpoints change, keeping scrolling behavior accurate as layouts adapt.
import EmblaCarousel from 'embla-carousel'
const wrapperNode = document.querySelector('.embla')const viewportNode = wrapperNode.querySelector('.embla__viewport')const emblaApi = EmblaCarousel(viewportNode, { slidesToScroll: 1, breakpoints: { '(min-width: 768px)': { slidesToScroll: 'auto' } }})import React from 'react'import useEmblaCarousel from 'embla-carousel-react'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel({ slidesToScroll: 1, breakpoints: { '(min-width: 768px)': { slidesToScroll: 'auto' } } })}<script setup>import useEmblaCarousel from 'embla-carousel-vue'
const [emblaRef] = useEmblaCarousel({ slidesToScroll: 1, breakpoints: { '(min-width: 768px)': { slidesToScroll: 'auto' } }})</script>import useEmblaCarousel from 'embla-carousel-solid'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel(() => ({ slidesToScroll: 1, breakpoints: { '(min-width: 768px)': { slidesToScroll: 'auto' } } }))}<script> import useEmblaCarousel from 'embla-carousel-svelte'
let options = { slidesToScroll: 1, breakpoints: { '(min-width: 768px)': { slidesToScroll: 'auto' } } }</script>Variable widths
The auto option is useful when you want to "page" slides regardless of whether 2, 3, or 4 fit in the viewport — you can keep the same configuration without changing slidesToScroll.
It's also handy for variable-width slides: Embla automatically groups slides based on how many fit inside the viewport, using each slide's computed size. This grouping adapts to responsive layouts, so each scroll moves one “page” of visible slides until the end.
Set slidesToScroll to auto and see it in action below: