Svelte 5 Snippets vs Slots: Why Slots Were Replaced

+15 Mana ✨

In Svelte 4 and earlier, components passed content using <slot> elements. While familiar, slots had significant limitations.

Slots in Svelte 4

svelte
<!-- Card.svelte (Svelte 4) -->
<div class="card">
  <slot name="header">Default Header</slot>
  <slot />  <!-- Default slot -->
  <slot name="footer" />
</div>
svelte
<!-- Usage -->
<Card>
  <h2 slot="header">My Title</h2>
  <p>Main content goes here</p>
  <button slot="footer">Save</button>
</Card>

The Problems with Slots

1. Awkward Slot Props

svelte
<!-- Child passes data up via slot props -->
<slot item={currentItem} />

<!-- Parent receives it with weird syntax -->
<List let:item>
  <p>{item.name}</p>
</List>

The let: syntax was non-obvious and confusing.

2. Component Boundary Restriction

Slots only worked at component boundaries — you couldn't reuse markup within a single component.

3. Type Safety Issues

Typing slot props was difficult and error-prone.

Enter Snippets

Snippets are reusable blocks of markup that work like functions:

svelte
{#snippet greeting(name)}
  <h1>Hello, {name}!</h1>
{/snippet}

{@render greeting('Alice')}
{@render greeting('Bob')}

Key Differences

FeatureSlots (Svelte 4)Snippets (Svelte 5)
ReusabilityOnly at component boundaryAnywhere in template
Parameterslet:prop syntaxFunction parameters
Type SafetyLimitedFull TypeScript support
RecursionNeeded <svelte:self>Just call the snippet
Default Content<slot>fallback</slot>Check if snippet exists

The Syntax

svelte
{#snippet name(param1, param2)}
  <!-- Template content -->
{/snippet}

{@render name(arg1, arg2)}

Snippets are defined with {#snippet} and rendered with {@render}.

✓ Completed