06 - Snippets
What are Snippets?
Snippets replace slots for passing content to components. More flexible and explicit than the old slot system.
Svelte 4 (Legacy — Slots)
<!-- Child.svelte -->
<div class="card">
<slot name="header" />
<slot />
<slot name="footer" />
</div><!-- Parent.svelte -->
<Card>
<h1 slot="header">Title</h1>
<p>Default content</p>
<p slot="footer">Footer</p>
</Card>Svelte 5 (Snippets)
<!-- Child.svelte -->
<script>
let { header, children, footer } = $props();
</script>
<div class="card">
{@render header()}
{@render children()}
{@render footer()}
</div><!-- Parent.svelte -->
<Card>
{#snippet header()}
<h1>Title</h1>
{/snippet}
<p>Default content</p>
{#snippet footer()}
<p>Footer</p>
{/snippet}
</Card>The key difference: snippets are just props (functions that return markup), so they're explicit, typed, and can accept parameters. children is a special snippet that captures any content not inside a named {#snippet}.
Basic Usage
children is the default snippet — it captures any content placed directly inside the component tags (not inside a named {#snippet}).
Child Component:
<!-- src/lib/components/Card.svelte -->
<script>
let { children } = $props();
</script>
<div class="card">
{@render children()}
</div>Parent:
<!-- src/routes/+page.svelte -->
<script>
import Card from '$lib/components/Card.svelte';
</script>
<Card>
<p>This is the content</p> <!-- becomes "children" -->
</Card>Named Snippets
Named snippets let you pass multiple blocks of content to specific locations in a child component.
Child:
<!-- src/lib/components/Card.svelte -->
<script>
let { header, footer } = $props();
</script>
<div class="card">
{@render header()}
<main>Main content</main>
{@render footer()}
</div>Parent:
<!-- src/routes/+page.svelte -->
<script>
import Card from '$lib/components/Card.svelte';
</script>
<Card>
{#snippet header()}
<h1>Title</h1>
{/snippet}
{#snippet footer()}
<p>Footer text</p>
{/snippet}
</Card>Snippets with Parameters
Snippets can receive data from the child component — the child calls {@render row(item)} with arguments, and the parent's snippet receives them.
Child:
<!-- src/lib/components/List.svelte -->
<script>
let { row } = $props();
let items = [1, 2, 3];
</script>
{#each items as item}
{@render row(item)} <!-- passes item to the parent's snippet -->
{/each}Parent:
<!-- src/routes/+page.svelte -->
<script>
import List from '$lib/components/List.svelte';
</script>
<List>
{#snippet row(item)}
<div>Item: {item}</div> <!-- receives item from child -->
{/snippet}
</List>Local Snippets
Snippets don't have to be passed to components — you can define and render them locally as reusable markup templates within the same file.
{#snippet card(title, content)}
<div class="card">
<h2>{title}</h2>
<p>{content}</p>
</div>
{/snippet}
{@render card('Title 1', 'Content 1')}
{@render card('Title 2', 'Content 2')}Key Points
- Replaces Svelte 4's
<slot>system - Snippets are props — explicit, typed, and can accept parameters
childrencaptures default content (not inside a named{#snippet}){#snippet name()}defines a snippet,{@render name()}renders it- Can be used locally as reusable markup templates or passed to child components
Interactive Example
<script>
import Card from './06-snippets-child.svelte';
import List from './06-snippets-list.svelte';
// Local snippet
{#snippet badge(text, color)}
<span class="badge" style="background: {color}">
{text}
</span>
{/snippet}
</script>
<div>
<h2>06 - Snippets Example</h2>
<h3>Basic Snippets (Named)</h3>
<Card>
{#snippet header()}
<h3>Card Title</h3>
{/snippet}
<p>This is the main content of the card.</p>
{#snippet footer()}
<small>Last updated: Today</small>
{/snippet}
</Card>
<h3>Snippets with Parameters</h3>
<List>
{#snippet row(item)}
<div class="row">
<span>{item.name}</span>
<span>${item.price}</span>
</div>
{/snippet}
</List>
<h3>Local Snippets</h3>
<div>
{@render badge('New', '#4CAF50')}
{@render badge('Sale', '#FF5722')}
{@render badge('Popular', '#2196F3')}
</div>
</div>
<style>
div { margin: 20px; }
h3 { margin-top: 20px; }
.badge {
display: inline-block;
padding: 5px 10px;
margin: 5px;
color: white;
border-radius: 3px;
font-size: 0.9em;
}
:global(.row) {
display: flex;
justify-content: space-between;
padding: 10px;
border-bottom: 1px solid #eee;
}
</style>