# Slick

> Migrate from Slick Carousel or React Slick to Blossom Carousel by replacing cloned-track behavior with native scrolling and CSS.

Slick Carousel creates a carousel around jQuery-managed markup, cloned slides, option objects, generated controls, and event callbacks. React Slick wraps the same model in React components.

Blossom keeps the carousel as a native scroll container. Layout, slide sizing, gaps, breakpoints, and snapping belong in CSS, while Blossom adds dragging and small convenience methods.

## Migration mindset

When moving from Slick Carousel to Blossom, migrate the carousel in three steps:

1. Replace Slick's generated track/list structure with a single `<BlossomCarousel>` root and direct children.
2. Move Slick options such as `slidesToShow`, `slidesToScroll`, `centerMode`, and `responsive` into CSS.
3. Replace Slick method calls and events with Blossom methods, native scroll APIs, and browser observers.

<note color="neutral" icon="i-lucide-lightbulb">

Slick often adds hidden markup and cloned slides. With Blossom, your source markup is the carousel markup.

</note>

## Installation

Remove Slick packages and install the matching Blossom package for your framework.

<code-group sync="migration-code-style">

```bash [Vue]
npm uninstall vue-slick-carousel slick-carousel
npm install @blossom-carousel/vue
```

```bash [React]
npm uninstall react-slick slick-carousel
npm install @blossom-carousel/react
```

```bash [Svelte]
npm uninstall slick-carousel jquery
npm install @blossom-carousel/svelte
```

```bash [Core]
npm uninstall slick-carousel jquery
npm install @blossom-carousel/core
```

</code-group>

Import the stylesheet from your framework package once in your app.

<code-group>

```js [Vue]
import "@blossom-carousel/vue/style.css";
```

```js [React]
import "@blossom-carousel/react/style.css";
```

```js [Svelte]
import "@blossom-carousel/svelte/style.css";
```

```js [Core]
import "@blossom-carousel/core/style.css";
```

```js [Web]
import "@blossom-carousel/web/style.css";
```

</code-group>

## Component structure

Slick and React Slick wrap your slides in a generated list and track. Blossom uses one scroll container with direct slide children.

<code-group sync="migration-code-style">

```vue [Vue]
<script setup lang="ts">
import VueSlickCarousel from "vue-slick-carousel"; // [!code --]
import "vue-slick-carousel/dist/vue-slick-carousel.css"; // [!code --]
import { BlossomCarousel } from "@blossom-carousel/vue"; // [!code ++]
import "@blossom-carousel/vue/style.css"; // [!code ++]

const slickSettings = { slidesToShow: 4, slidesToScroll: 1 }; // [!code --]
</script>

<template>
  <VueSlickCarousel v-bind="slickSettings"> <!-- [!code --] -->
    <div>Slide 1</div> <!-- [!code --] -->
    <div>Slide 2</div> <!-- [!code --] -->
    <div>Slide 3</div> <!-- [!code --] -->
  </VueSlickCarousel> <!-- [!code --] -->
  <BlossomCarousel class="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> <!-- [!code ++] -->
    <div class="slide snap-start">Slide 1</div> <!-- [!code ++] -->
    <div class="slide snap-start">Slide 2</div> <!-- [!code ++] -->
    <div class="slide snap-start">Slide 3</div> <!-- [!code ++] -->
  </BlossomCarousel> <!-- [!code ++] -->
</template>
```

```tsx [React]
import Slider from "react-slick"; // [!code --]
import "slick-carousel/slick/slick.css"; // [!code --]
import { BlossomCarousel } from "@blossom-carousel/react"; // [!code ++]
import "@blossom-carousel/react/style.css"; // [!code ++]

export function Carousel() {
  return (
    <Slider slidesToShow={4} slidesToScroll={1}> {/* [!code --] */}
      <div>Slide 1</div> {/* [!code --] */}
      <div>Slide 2</div> {/* [!code --] */}
      <div>Slide 3</div> {/* [!code --] */}
    </Slider> {/* [!code --] */}
    <BlossomCarousel className="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> {/* [!code ++] */}
      <div className="slide snap-start">Slide 1</div> {/* [!code ++] */}
      <div className="slide snap-start">Slide 2</div> {/* [!code ++] */}
      <div className="slide snap-start">Slide 3</div> {/* [!code ++] */}
    </BlossomCarousel> {/* [!code ++] */}
  );
}
```

```svelte [Svelte]
<script>
  import { onMount } from "svelte"; // [!code --]
  import $ from "jquery"; // [!code --]
  import "slick-carousel"; // [!code --]
  import "slick-carousel/slick/slick.css"; // [!code --]
  import { BlossomCarousel } from "@blossom-carousel/svelte"; // [!code ++]
  import "@blossom-carousel/svelte/style.css"; // [!code ++]

  let carousel; // [!code --]

  onMount(() => { // [!code --]
    const slick = $(carousel).slick({ slidesToShow: 4, slidesToScroll: 1 }); // [!code --]
    return () => slick.slick("unslick"); // [!code --]
  }); // [!code --]
</script>

<div class="carousel" bind:this={carousel}> <!-- [!code --] -->
  <div>Slide 1</div> <!-- [!code --] -->
  <div>Slide 2</div> <!-- [!code --] -->
  <div>Slide 3</div> <!-- [!code --] -->
</div> <!-- [!code --] -->
<BlossomCarousel class="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> <!-- [!code ++] -->
  <div class="slide snap-start">Slide 1</div> <!-- [!code ++] -->
  <div class="slide snap-start">Slide 2</div> <!-- [!code ++] -->
  <div class="slide snap-start">Slide 3</div> <!-- [!code ++] -->
</BlossomCarousel> <!-- [!code ++] -->
```

```html [jQuery]
<div class="carousel"> <!-- [!code --] -->
  <div>Slide 1</div> <!-- [!code --] -->
  <div>Slide 2</div> <!-- [!code --] -->
  <div>Slide 3</div> <!-- [!code --] -->
</div> <!-- [!code --] -->
<blossom-carousel class="carousel grid! grid-auto-cols grid-cols-[calc((100% - 3rem) / 4)] gap-4"> <!-- [!code ++] -->
  <div class="slide snap-start">Slide 1</div> <!-- [!code ++] -->
  <div class="slide snap-start">Slide 2</div> <!-- [!code ++] -->
  <div class="slide snap-start">Slide 3</div> <!-- [!code ++] -->
</blossom-carousel> <!-- [!code ++] -->
```

</code-group>

## Options

Slick options describe how its track should move, clone slides, and generate UI. In Blossom, most of those choices become CSS or small browser APIs.

<table>
<thead>
  <tr>
    <th>
      Slick concept
    </th>
    
    <th>
      Blossom approach
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        slidesToShow
      </code>
    </td>
    
    <td>
      Use CSS <code>
        grid-auto-columns
      </code>
      
       to define the relative width of slides.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        slidesToScroll
      </code>
    </td>
    
    <td>
      Use CSS <code>
        scroll-snap-align
      </code>
      
       within <code>
        :nth-child(xn)
      </code>
      
       or nest slides in groups.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        centerMode
      </code>
    </td>
    
    <td>
      Use <code>
        scroll-snap-align: center
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        variableWidth
      </code>
    </td>
    
    <td>
      Let slides size themselves with CSS.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        adaptiveHeight
      </code>
    </td>
    
    <td>
      Let content define height, or update layout with <code>
        ResizeObserver
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        responsive
      </code>
    </td>
    
    <td>
      Use CSS media queries and container queries.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        infinite
      </code>
    </td>
    
    <td>
      Prefer bounded native scrolling, or use the experimental repeat pattern when an infinite effect is required. See <a href="/docs/examples/experimental/repeat">
        Repeat example
      </a>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        draggable
      </code>
      
       / <code>
        swipe
      </code>
    </td>
    
    <td>
      Use CSS <code>
        overflow: hidden
      </code>
      
       on the carousel to disable dragging and scrolling.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        arrows
      </code>
    </td>
    
    <td>
      Use <code>
        <BlossomPrev>
      </code>
      
       and <code>
        <BlossomNext>
      </code>
      
      . See <a href="/docs/examples/basic/buttons">
        Buttons example
      </a>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dots
      </code>
    </td>
    
    <td>
      Use <code>
        <BlossomDots for="my-carousel">
      </code>
      
       and mark slides with <code>
        data-blossom-slide
      </code>
      
      . See <a href="/docs/examples/basic/dots">
        Dots example
      </a>
      
      .
    </td>
  </tr>
</tbody>
</table>

For example, this Slick setup:

```js [Slick]
$(".carousel").slick({
  slidesToShow: 1,
  slidesToScroll: 1,
  centerMode: true,
  responsive: [{ breakpoint: 768, settings: { slidesToShow: 3 } }],
});
```

becomes CSS:

```css [Blossom]
.carousel {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  gap: 1rem;
  scroll-snap-type: inline mandatory;
}

.slide {
  scroll-snap-align: center;
}

@media (min-width: 768px) {
  .carousel {
    grid-auto-columns: calc((100% - 2rem) / 3);
  }
}
```

## Controls

Slick controls call methods on the Slick instance. Blossom provides `<BlossomPrev>`, `<BlossomNext>`, and `<BlossomDots>` components that link to the carousel through matching `id` and `for` props.

```ts
$(".carousel").slick("slickPrev"); // [!code --]
$(".carousel").slick("slickNext"); // [!code --]
```

```html
<BlossomCarousel id="gallery" class="carousel">
  <div data-blossom-slide class="slide">Slide 1</div>
  ...
</BlossomCarousel>

<div class="controls">
  <BlossomPrev for="gallery" />
  <BlossomNext for="gallery" />
</div>

<BlossomDots for="gallery" />
```

For direct slide navigation, call `goTo(index)` on the carousel. It scrolls to the slide at that zero-based index, counting slides marked with `data-blossom-slide`. Reach the carousel through a template ref in Vue, a `ref` in React, `bind:this` in Svelte, or the `<blossom-carousel>` element itself.

```ts
carousel.goTo(index);
carousel.goTo(index, { behavior: "instant" });
```

## API

Slick commonly uses `afterChange` to track the current slide.

With Blossom, read the active slide from `useBlossomNavigation` in Vue, React, and Svelte. Pass the carousel `id`; it returns `activeIndex`, `count`, `canPrev`, and `canNext`, and updates during drag and free scrolling too.

```ts
$(".carousel").on("afterChange", (_event, _slick, currentSlide) => { // [!code --]
  setSelectedIndex(currentSlide); // [!code --]
}); // [!code --]

const nav = useBlossomNavigation("gallery"); // [!code ++]
```

In React and Svelte, read `nav.activeIndex`. In Vue, `nav` is a ref, so read `nav.value.activeIndex` in script or `nav.activeIndex` in the template. Don't destructure the result in Svelte; that loses reactivity.

With Web Components, listen for the native `scrollsnapchange` event where it's supported:

```ts
const slides = Array.from(carousel.querySelectorAll("[data-blossom-slide]"));

carousel.addEventListener("scrollsnapchange", (event) => {
  setSelectedIndex(slides.indexOf(event.snapTargetInline));
});
```

## Features

Slick features usually become either small Blossom wrappers or native platform features.

<table>
<thead>
  <tr>
    <th>
      Slick feature
    </th>
    
    <th>
      Blossom replacement
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      Arrows
    </td>
    
    <td>
      <code>
        <BlossomPrev>
      </code>
      
       and <code>
        <BlossomNext>
      </code>
      
       components.
    </td>
  </tr>
  
  <tr>
    <td>
      Dots
    </td>
    
    <td>
      <code>
        <BlossomDots>
      </code>
      
       with <code>
        data-blossom-slide
      </code>
      
       on slides.
    </td>
  </tr>
  
  <tr>
    <td>
      Autoplay
    </td>
    
    <td>
      A manual timer that scrolls the next slide into view.
    </td>
  </tr>
  
  <tr>
    <td>
      Fade
    </td>
    
    <td>
      CSS scroll-driven animations or intersection state.
    </td>
  </tr>
  
  <tr>
    <td>
      Lazy load
    </td>
    
    <td>
      Native <code>
        loading="lazy"
      </code>
      
       or framework image components.
    </td>
  </tr>
  
  <tr>
    <td>
      Rows
    </td>
    
    <td>
      CSS grid.
    </td>
  </tr>
  
  <tr>
    <td>
      Syncing sliders
    </td>
    
    <td>
      Shared selected state plus <code>
        goTo()
      </code>
      
      .
    </td>
  </tr>
</tbody>
</table>

Rebuild Slick features deliberately. Native scrolling often replaces more of Slick than expected.

## Lifecycle

Slicks's and Blossom's lifecycle methods are similar.

<note color="neutral" icon="i-lucide-lightbulb">

Blossom initializes automatically when using framework components.

</note>

```ts
$(".carousel").slick("refresh"); // [!code --]
$(".carousel").slick("unslick"); // [!code --]
blossom.init(); // [!code ++]
blossom.destroy(); // [!code ++]
```

## Migration checklist

- Remove Slick packages and install the matching Blossom package.
- Import the stylesheet from your framework package once (for example `@blossom-carousel/vue/style.css`).
- Replace Slick markup and generated track assumptions with `<BlossomCarousel>` and direct slide children.
- Move slide sizing, gaps, snapping, center mode, and responsive behavior into CSS.
- Replace `slickPrev` and `slickNext` with `<BlossomPrev>` and `<BlossomNext>`.
- Replace `slickGoTo` with `goTo(index)` on the carousel.
- Replace Slick events with `useBlossomNavigation` (or `scrollsnapchange` for Web Components).
- Rebuild only the Slick features your carousel still needs.

## Next steps

- [Installation](/docs/getting-started/installation) - Pick the package for your framework.
- [Snapping](/docs/examples/basic/snap) - Configure scroll snap behavior with CSS.
- [Buttons](/docs/examples/basic/buttons) - Add previous and next controls.
- [Dots](/docs/examples/basic/dots) - Add dot markers with `<BlossomDots>`.
- [Repeat](/docs/examples/experimental/repeat) - Explore an experimental repeating carousel pattern.
