Installing Locomotive Scroll with Svelte 5 and SvelteKit

Installation

First, let's install the necessary packages:

npm install locomotive-scroll@beta

Create a Locomotive Scroll Store

We'll start by creating a Svelte store to manage our Locomotive Scroll instance:

import { writable } from "svelte/store";

export const locomotiveScroll = writable(null);

export async function initLocomotiveScroll(options = {}) {
  if (typeof window !== "undefined") {
    const LocomotiveScroll = (await import("locomotive-scroll")).default;
    const instance = new LocomotiveScroll({
      el: document.querySelector("[data-scroll-container]"),
      lenisOptions: {
        ...options,
      },
    });
    locomotiveScroll.set(instance);
    return instance;
  }
}

This code creates a Svelte store called locomotiveScroll and an initialization function initLocomotiveScroll. The function dynamically imports Locomotive Scroll, creates an instance, and stores it in the locomotiveScroll store.

The initLocomotiveScroll function is designed to work in a browser environment, which is why it checks if window is defined before proceeding.

Set Up the Layout Component

Next, we'll set up our layout component to initialize Locomotive Scroll:

<script>
	import { browser } from '$app/environment';
	import { afterNavigate } from '$app/navigation';
	import { page } from '$app/stores';
	import { initLocomotiveScroll, locomotiveScroll } from './locomotiveScroll.js';
	import './locomotive-scroll.css';

	let scrollInstance = $state(null);

	const { children, settings } = $props();

	async function initializeScroll() {
			if (scrollInstance) {
					scrollInstance.destroy();
			}
			console.log('Initializing new scroll instance');
			scrollInstance = await initLocomotiveScroll(settings);
	}

	afterNavigate(async () => {
			if (browser) {
					await initializeScroll();
					scrollInstance.scrollTo(0, { duration: 100, disableLerp: true });
			}
	});
</script>

<div data-scroll-container>
	{@render children()}
</div>

This layout component initializes Locomotive Scroll when the component mounts and updates it when the route changes. It also ensures that Locomotive Scroll is destroyed when the component unmounts.

The $state, $props(), and $effect syntax are specific to Svelte 5's new reactive primitives. They replace the older let, export let, and $: syntax respectively.

Using Locomotive Scroll in a Page Component

Finally, let's see how to use Locomotive Scroll in a page component:

<script>
	import { browser } from '$app/environment';
	import { locomotiveScroll } from '$lib/locomotiveScroll';

	$effect(() => {
		if (browser && $locomotiveScroll) {
			console.log('Locomotive Scroll is ready');
			// You can now use $locomotiveScroll methods
		}
	});
</script>

<div data-scroll-section class="h-[1000px] flex flex-col justify-center items-center">
	<h2 data-scroll data-scroll-speed="0.8">What's up?</h2>
	<p data-scroll data-scroll-speed="0.5">😬</p>
</div>

This page component demonstrates how to access the Locomotive Scroll instance and use its data attributes for scroll animations.

Result

When implemented correctly, you should see a smooth scrolling effect with animated elements. Here's a visual representation of what you might see:

[A webpage with a centered column of text]

What's up?

😬

[The text "What's up?" moves slightly as you scroll, while the emoji moves more dramatically due to its higher scroll speed]

Explanation of Key Concepts

  1. Svelte Stores: The locomotiveScroll store is used to make the Locomotive Scroll instance accessible throughout the app.

  2. Dynamic Imports: Locomotive Scroll is imported dynamically to ensure it only loads in the browser environment.

  3. Lifecycle Management: The layout component initializes Locomotive Scroll on mount and destroys it on unmount.

  4. Route Change Handling: The scroll instance is updated when the route changes to ensure smooth transitions between pages.

  5. Data Attributes: Locomotive Scroll uses data attributes like data-scroll-container, data-scroll-section, and data-scroll to manage scrolling behavior and animations.

Last updated