Slots and Snippets
Letting a parent component inject markup into a child, from the classic <slot> to Svelte 5's snippets.
阅读需 2 分钟
Props pass data into a component. Sometimes you want to pass markup instead — think of a Card component that doesn't know or care what's inside it, only that it should wrap whatever content a caller provides with some consistent styling.
Children content
In Svelte 5, the default content placed between a component's opening and closing tags is exposed to that component as a special children prop, which you render with {@render}:
<!-- Card.svelte -->
<script>
let { children } = $props();
</script>
<div class="card">
{@render children()}
</div><!-- App.svelte -->
<script>
import Card from './Card.svelte';
</script>
<Card>
<h3>Title</h3>
<p>Some content inside the card.</p>
</Card>Card never needed to know it was rendering a heading and a paragraph — it just rendered whatever children it was handed. This replaces the <slot /> element from Svelte 4; if you see <slot /> in older code or tutorials, {@render children()} is its Svelte 5 equivalent.
Named snippets for more than one region
A component sometimes needs more than one placeholder — a header and a footer, say, that a caller fills in independently. Svelte 5's {#snippet} block lets a caller define more than one named piece of markup and pass each as its own prop:
<!-- Panel.svelte -->
<script>
let { header, children } = $props();
</script>
<div class="panel">
<div class="panel-header">{@render header()}</div>
<div class="panel-body">{@render children()}</div>
</div><!-- App.svelte -->
<script>
import Panel from './Panel.svelte';
</script>
<Panel>
{#snippet header()}
<strong>Settings</strong>
{/snippet}
<p>Panel content goes here.</p>
</Panel>header is passed as a named snippet, while the plain content outside any {#snippet} block still becomes children — the two work side by side.
Snippets can take parameters
A snippet is really just a chunk of reusable markup, and like a function, it can accept arguments:
<!-- List.svelte -->
<script>
let { items, row } = $props();
</script>
<ul>
{#each items as item}
<li>{@render row(item)}</li>
{/each}
</ul><List items={users} >
{#snippet row(user)}
<strong>{user.name}</strong> — {user.email}
{/snippet}
</List>This is the closest Svelte gets to a "render prop": List handles the looping, but delegates exactly how each row looks to whoever's using it — reusable structure, customizable presentation.