06 - Snippets
📋 Jump to Takeaways🎁 What if the content you pass into a component could take arguments, like a function, so the child decides the data and the parent decides how it looks?
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')}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>Key Takeaways
- 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
🎁 Snippets let a parent hand markup to a child. But how does that child tell the parent when a button gets clicked, and what changed about event handlers in Svelte 5?