Svelte and SvelteKit
Install
pnpm add @blossom-carousel/svelte
bun add @blossom-carousel/svelte
yarn add @blossom-carousel/svelte
npm install @blossom-carousel/svelte
Svelte usage
@blossom-carousel/svelte2.x requires Svelte 5 (runes + snippets) and drops Svelte 4 support. If you're on Svelte 4, stay on @blossom-carousel/svelte@1.<script>
import { BlossomCarousel } from "@blossom-carousel/svelte";
import "@blossom-carousel/svelte/style.css";
const slides = Array.from({ length: 12 }, (_, index) => index + 1);
</script>
<BlossomCarousel>
{#each slides as slide (slide)}
<div>Slide {slide}</div>
{/each}
</BlossomCarousel>
SvelteKit setup
Import the stylesheet from the root layout.
<script>
import "@blossom-carousel/svelte/style.css";
let { children } = $props();
</script>
{@render children()}
Then import the component in the page or component that renders the carousel.
<script>
import { BlossomCarousel } from "@blossom-carousel/svelte";
</script>
<BlossomCarousel>{/* slides */}</BlossomCarousel>
Semantic root element
Use as="ul" for list-like carousels.
<BlossomCarousel as="ul">
{#each slides as slide (slide)}
<li>Slide {slide}</li>
{/each}
</BlossomCarousel>
Navigation controls
Place previous, next, and dot controls outside the carousel with <BlossomPrev>, <BlossomNext>, and <BlossomDots>. Link them to the carousel with an id on <BlossomCarousel>, and a matching forId prop on each control and mark slides with data-blossom-slide.
<BlossomCarousel id="my-carousel">
{#each slides as slide (slide)}
<div data-blossom-slide>Slide {slide}</div>
{/each}
</BlossomCarousel>
<BlossomPrev forId="my-carousel" />
<BlossomDots forId="my-carousel" />
<BlossomNext forId="my-carousel" />
BlossomDots renders one button per marked slide server-side, before any client JS runs, by reading the slide count that BlossomCarousel registers when it renders. Controls placed before the carousel start at zero dots and fill in on the client.Prev/Next Buttons
<BlossomPrev> and <BlossomNext> are aware of configured scroll-snap and will navigate between snap points. When no scroll-snap is configured, they will slide the carousel proportionally.
Slot your own content to replace the default button icon.
<BlossomPrev forId="my-carousel">
<span>Previous</span>
</BlossomPrev>
Dots
<BlossomDots> renders one button per slide marked with data-blossom-slide.
Default styles can be themed with CSS custom properties on the component or any ancestor:
/* defaults */
{
--blossom-dot-size: 0.625rem;
--blossom-dot-radius: 50%;
--blossom-dot-color: currentColor;
--blossom-dot-opacity: 0.35;
--blossom-dot-hover-opacity: 0.6;
--blossom-dot-active-opacity: 1;
}
To bring your own dots, provide a default slot and render <BlossomDot> inside it. This will configure the dot as a <button> with navigation wired up.
Now you can style the dot as you please and attach any button attributes you need.
<BlossomDots forId="my-carousel">
{#snippet children({ index, active })}
<BlossomDot
class="my-dot"
data-active={active}
aria-label="Photo {index + 1}"
>
{index + 1}
</BlossomDot>
{/snippet}
</BlossomDots>
Listening for commands
Listen for command events on the carousel to know when any navigation control is triggered:
- previous (
--blossom-prev) - next (
--blossom-next) - dot (
--blossom-goto-{index}).
These events are not fired by drag or free scrolling. Read event.command (or event.detail.command where the Invoker Commands polyfill applies).
<script>
function handleCommand(event) {
const command = event?.command || event?.detail?.command;
}
</script>
<BlossomCarousel oncommand={handleCommand}>
{#each slides as slide (slide)}
<div data-blossom-slide>Slide {slide}</div>
{/each}
</BlossomCarousel>
See the Buttons and Dots examples for live demos.
Overscroll API
Tap into Blossom's drag engine's overscroll behavior to create your own style.
<script>
function onOverscroll(event) {
// prevent and overwrite Blossom's default rubberbanding effect
event.preventDefault();
const overScroll = event.detail.left;
Array.from(event.target.children).forEach((slide) => {
slide.style.transform = `scale(${1 - overScroll * 0.1})`;
});
}
</script>
<BlossomCarousel onoverscroll={onOverscroll}>
{#each Array.from({ length: 12 }, (_, index) => index + 1) as slide (slide)}
<div>Slide {slide}</div>
{/each}
</BlossomCarousel>
BlossomCarousel forwards unrecognized props to its root element, so onoverscroll attaches directly via addEventListener. There's no exposed ref to the root DOM node, so read the target off the event (event.target) rather than binding a ref.