Alignments
This guide explains how to control and customize carousel alignment in Embla Carousel.
Prerequisites
Before continuing with this guide, make sure you've completed the following:
Understanding alignment
Embla measures each slide's actual layout position and size — the values the browser computes after rendering. It then applies the selected align option (start, center, or end) to calculate where each snap point should land within the carousel.
The align option only affects carousels where slides are less than 100% of the viewport width, since full-width slides already occupy the entire scroll area.
Setting alignment
You can configure the alignment using the align option when initializing Embla:
import EmblaCarousel from 'embla-carousel'
const wrapperNode = document.querySelector('.embla')const viewportNode = wrapperNode.querySelector('.embla__viewport')const emblaApi = EmblaCarousel(viewportNode, { align: 'center' })<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({ align: 'center' })
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({ align: 'center' })</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(() => ({ align: 'center' }))
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 = { align: 'center' }</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>The align option defines how slides align relative to the viewport:
start— Aligns the slide's start edge (left in LTR, right in RTL, top for vertical).center(default) — Aligns the slide's center with the viewport center.end— Aligns the slide's end edge (right in LTR, left in RTL, bottom for vertical).
Warning: Do not use CSS layout properties (like justify-content,
align-items) or CSS transforms on the carousel container to change
alignment along the scroll axis. Those rules change the position of slides in
ways that change the computed offsets Embla measures, which breaks snapping
and can produce unexpected scroll behavior.
Breakpoints
You can make carousel alignment responsive by defining different align values for specific viewport sizes using the breakpoints option.
Embla automatically re-evaluates slide positions when breakpoints change, ensuring that scroll snaps stay accurate as layouts adapt.
import EmblaCarousel from 'embla-carousel'
const wrapperNode = document.querySelector('.embla')const viewportNode = wrapperNode.querySelector('.embla__viewport')const emblaApi = EmblaCarousel(viewportNode, { align: 'center', breakpoints: { '(min-width: 768px)': { align: 'start' } }})import React from 'react'import useEmblaCarousel from 'embla-carousel-react'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel({ align: 'center', breakpoints: { '(min-width: 768px)': { align: 'start' } } })}<script setup>import useEmblaCarousel from 'embla-carousel-vue'
const [emblaRef] = useEmblaCarousel({ align: 'center', breakpoints: { '(min-width: 768px)': { align: 'start' } }})</script>import useEmblaCarousel from 'embla-carousel-solid'
export function EmblaCarousel() { const [emblaRef] = useEmblaCarousel(() => ({ align: 'center', breakpoints: { '(min-width: 768px)': { align: 'start' } } }))}<script> import useEmblaCarousel from 'embla-carousel-svelte'
let options = { align: 'center', breakpoints: { '(min-width: 768px)': { align: 'start' } } }</script>Contain scroll
For non-looping carousels, Embla adjusts the alignment to prevent empty space from appearing at the start or end of the scroll area. This can make the first and last slides appear slightly off-alignment — but once you scroll, the slides in between align as expected.
This behavior is controlled by the containScroll option, which is enabled by default.
If you prefer to keep a consistent alignment at all times (even if that means extra space at the edges), set containScroll: false.
Try it out below:
The containScroll option controls how Embla handles empty space at the start and end of the scroll area:
trimSnaps(default) — Prevents empty space at the beginning and end by adjusting alignment when necessary.keepSnaps— Similar totrimSnaps, but ensures that each slide is a separate snap point, even when trimming space.false— Disables this behavior entirely, allowing empty space at the edges to maintain consistent alignment — just like looping carousels align.