Svelte quickstart

By the end of this page you'll have a gradient with a cursor trail running in your Svelte app, sized with CSS and driven by state.

Installing the package

Shaders is one package for every framework:

npm install shaders

The Svelte components come from shaders/svelte.

Rendering your first effect

Let's start with a gradient and put a cursor trail on top of it. Add this component anywhere in your app:

<script>
  import { Shader, LinearGradient, CursorTrail } from 'shaders/svelte'
</script>

<Shader class="w-full h-64">
  <LinearGradient colorA="#0f172a" colorB="#7c3aed" />
  <CursorTrail />
</Shader>

Move your cursor over the canvas to see the trail.

<Shader> renders a single <canvas>. The components inside it are layers, drawn in order like layers in Figma: the gradient first, then the trail on top.

Sizing the canvas

The canvas has no size of its own. It takes whatever size you give <Shader> through class or style:

<!-- Fill the viewport -->
<Shader class="w-screen h-screen">
  <LinearGradient />
</Shader>

<!-- Fixed size -->
<Shader style="width: 600px; height: 400px">
  <LinearGradient />
</Shader>

<!-- Full width, 16:9 -->
<Shader class="w-full aspect-video">
  <LinearGradient />
</Shader>

Style <Shader>, not the <canvas> inside it. The internal markup can change between releases.

Setting props

Each component takes props the same way any Svelte component does. Strings can be passed plain; numbers and expressions go in {}:

<Shader class="w-full h-64">
  <LinearGradient
    colorA="#ff6b6b"
    colorB="#4ecdc4"
    angle={45}
    colorSpace="oklch"
  />
</Shader>

colorSpace="oklch" blends the two colors through a perceptual color space, so the middle of the gradient stays bright instead of going gray. Every component's props, with defaults and ranges, are in the component docs.

Driving a prop from state

Props accept $state like any other Svelte prop (in Svelte 4, a plain let). We'll wire the gradient's angle to a range input:

<script>
  import { Shader, LinearGradient } from 'shaders/svelte'

  let angle = $state(0)
</script>

<Shader class="w-full h-64">
  <LinearGradient colorA="#ff6b6b" colorB="#4ecdc4" {angle} />
</Shader>

<input type="range" min="0" max="360" bind:value={angle} />

Drag the slider and the gradient turns on the next frame. Changing angle updates a value on the GPU; the effect doesn't recompile.

Using SvelteKit and server rendering

Shaders needs a browser with a GPU, so it can't render on the server. In SvelteKit you don't need to do anything: <Shader> renders nothing on the server and starts on the client. The SvelteKit and SSR guide covers browser-only code, conditional rendering, and lazy loading.

Next steps