Flickity
Flickity creates a carousel from cell elements, option objects, generated controls, selected-cell state, and a JavaScript instance.
Blossom keeps the carousel as a native scroll container. Layout, slide sizing, cell alignment, spacing, and responsive behavior belong in CSS, while Blossom adds dragging and small convenience methods.
Migration mindset
When moving from Flickity to Blossom, migrate the carousel in three steps:
- Replace Flickity initialization with a single
<BlossomCarousel>root and direct children. - Move Flickity options such as
cellAlign,contain,wrapAround, andgroupCellsinto CSS or native scrolling. - Replace Flickity methods and events with Blossom methods, native scroll APIs, and browser observers.
Installation
Remove Flickity and install the matching Blossom package for your framework.
npm uninstall vue-flickity flickity
npm install @blossom-carousel/vue
npm uninstall react-flickity-component flickity
npm install @blossom-carousel/react
npm uninstall flickity
npm install @blossom-carousel/svelte
npm uninstall flickity
npm install @blossom-carousel/core
Import Blossom's core stylesheet once in your app.
import "@blossom-carousel/core/style.css";
Component structure
Flickity initializes behavior on an element and treats its children as cells. Blossom keeps that direct-child model, but the root itself is the native scroll container.
<script setup lang="ts">
import Flickity from "vue-flickity";import "flickity/css/flickity.css";import { BlossomCarousel } from "@blossom-carousel/vue";import "@blossom-carousel/core/style.css";</script>
<template>
<Flickity :options="{ cellAlign: "left", contain: true }"> <div class="carousel-cell">Slide 1</div> <div class="carousel-cell">Slide 2</div> <div class="carousel-cell">Slide 3</div> </Flickity> <BlossomCarousel class="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> <div class="slide snap-start">Slide 1</div> <div class="slide snap-start">Slide 2</div> <div class="slide snap-start">Slide 3</div> </BlossomCarousel></template>
import Flickity from "react-flickity-component";import "flickity/css/flickity.css";import { BlossomCarousel } from "@blossom-carousel/react";import "@blossom-carousel/core/style.css";
export function Carousel() {
return (
<Flickity options={{ cellAlign: "left", contain: true }}> <div className="carousel-cell">Slide 1</div> <div className="carousel-cell">Slide 2</div> <div className="carousel-cell">Slide 3</div> </Flickity> <BlossomCarousel className="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> <div className="slide snap-start">Slide 1</div> <div className="slide snap-start">Slide 2</div> <div className="slide snap-start">Slide 3</div> </BlossomCarousel> );
}
<script>
import { onMount } from "svelte"; import Flickity from "flickity"; import "flickity/css/flickity.css"; import BlossomCarousel from "@blossom-carousel/svelte"; import "@blossom-carousel/core/style.css";
let carousel;
onMount(() => { const flickity = new Flickity(carousel, { cellAlign: "left", contain: true }); return () => flickity.destroy(); });</script>
<div class="carousel" bind:this={carousel}> <div class="carousel-cell">Slide 1</div> <div class="carousel-cell">Slide 2</div> <div class="carousel-cell">Slide 3</div></div><BlossomCarousel class="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> <div class="slide snap-start">Slide 1</div> <div class="slide snap-start">Slide 2</div> <div class="slide snap-start">Slide 3</div></BlossomCarousel><div class="carousel"> <div class="carousel-cell">Slide 1</div> <div class="carousel-cell">Slide 2</div> <div class="carousel-cell">Slide 3</div></div><blossom-carousel class="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> <div class="slide snap-start">Slide 1</div> <div class="slide snap-start">Slide 2</div> <div class="slide snap-start">Slide 3</div></blossom-carousel>Options
Flickity options describe how its engine measures and aligns cells. In Blossom, most of those choices become CSS and native scroll behavior.
| Flickity concept | Blossom approach |
|---|---|
cellAlign: "left" | Use scroll-snap-align: start. |
cellAlign: "center" | Use scroll-snap-align: center. |
contain | Use native scroll bounds, padding, and scroll-padding. |
groupCells | Create grouped slide elements or use native scrolling to target every nth slide. |
wrapAround | Prefer bounded native scrolling, or use the experimental repeat pattern when an infinite effect is required. See Repeat example. |
freeScroll | Omit scroll-snap-align or use scroll-snap-type: proximity. |
rightToLeft | Use dir="rtl" or CSS direction: rtl. |
adaptiveHeight | Let content define height, or update layout with ResizeObserver. |
prevNextButtons | Use buttons that call prev() and next(). See Buttons example. |
pageDots | Build dots from IntersectionObserver or scrollsnapchange. See Dots example. |
For example, this Flickity setup:
const flkty = new Flickity(".carousel", {
cellAlign: "center",
contain: true,
groupCells: true,
wrapAround: false,
});
becomes CSS:
.carousel {
display: grid;
grid-auto-flow: column;
grid-auto-columns: 25%;
gap: 1rem;
scroll-snap-type: inline mandatory;
scroll-padding-inline: 10%;
}
.slide {
scroll-snap-align: center;
}
Controls
Flickity controls call methods on the Flickity instance. Blossom exposes prev() and next() on the carousel element or component ref.
flkty.previous();flkty.next();blossom.value.prev();blossom.value.next();For direct slide navigation, use native scrolling on the target slide.
slides[index].scrollIntoView({
behavior: "smooth",
inline: "center",
block: "nearest",
});
API
Flickity commonly uses the select event and selectedIndex to track the active cell.
With Blossom, the carousel is a real scroll container, so use browser APIs such as IntersectionObserver, scrollsnapchange, or scroll events depending on the browser support you need.
flkty.on("select", () => { setSelectedIndex(flkty.selectedIndex);});
carousel.addEventListener("scrollsnapchange", (event) => { setSelectedIndex(event.detail.index);});
Or use IntersectionObserver for wider browser support
const slides = Array.from(carousel.children);const observer = new IntersectionObserver( (entries) => { const activeEntry = entries.find((entry) => entry.isIntersecting); if (activeEntry) { setSelectedIndex(slides.indexOf(activeEntry.target)); } }, { root: carousel, threshold: 0.5 },);slides.forEach((slide) => observer.observe(slide));Features
Flickity features usually become either small Blossom wrappers or native platform features.
| Flickity feature | Blossom replacement |
|---|---|
| Previous / next buttons | Buttons that call prev() and next(). |
| Page dots | Dots backed by IntersectionObserver or scrollsnapchange. |
| Auto play | A timer that calls next() or scrolls the next slide into view. |
| Lazy load | Native loading="lazy" and content-visibility: auto. |
| As nav for | Shared selected state plus scrollIntoView(). |
| Images loaded | Native image loading events or ResizeObserver if layout depends on image size. |
| Fade | CSS scroll-driven animations or intersection state. |
Keep feature migrations small. Start from a working Blossom carousel, then add behavior back only if the product still needs it.
Lifecycle
Flickity's and Blossom's lifecycle methods are similar.
flkty.resize();flkty.destroy();blossom.init();blossom.destroy();Migration checklist
- Remove Flickity packages and install the matching Blossom package.
- Import
@blossom-carousel/core/style.cssonce. - Replace Flickity initialization with
<BlossomCarousel>and direct slide children. - Move cell sizing, alignment, gaps, snapping, direction, and breakpoints into CSS.
- Replace
previous()andnext()withprev()andnext(). - Replace
select(index)withscrollIntoView()or nativescrollTo(). - Replace Flickity events with browser observers or scroll snap events.
- Rebuild only the Flickity features your carousel still needs.
Next steps
- Installation - Pick the package for your framework.
- Snapping - Configure scroll snap behavior with CSS.
- Buttons - Add previous and next controls.
- Dots - Track the active slide with browser APIs.
- Repeat - Explore an experimental repeating carousel pattern.