Snippets are a way to create reusable chunks of markup inside your components. They’re more powerful and flexible than Svelte 4’s slots.
Basic Syntax
{# snippet name ()}...{/ snippet }
With parameters:
{# snippet name ( param1 , param2 , paramN )}...{/ snippet }
Creating Snippets
Define reusable markup to avoid duplication:
{# snippet figure ( image )}
< figure >
< img src = { image . src } alt = { image . caption } width = { image . width } height = { image . height } />
< figcaption > { image . caption } </ figcaption >
</ figure >
{/ snippet }
{# each images as image }
{# if image . href }
< a href = { image . href } >
{@ render figure ( image )}
</ a >
{: else }
{@ render figure ( image )}
{/ if }
{/ each }
Rendering Snippets
Use {@render} to render a snippet:
{@ render snippetName ( arg1 , arg2 )}
Snippet Parameters
Snippets can have parameters with default values and destructuring:
Default Values {# snippet greet ( name = 'World' )}
< p > Hello { name } ! </ p >
{/ snippet }
{@ render greet ()}
{@ render greet ( 'Alice' )}
Destructuring {# snippet userCard ({ name , email , avatar })}
< div class = "card" >
< img src = { avatar } alt = { name } />
< h3 > { name } </ h3 >
< p > { email } </ p >
</ div >
{/ snippet }
{@ render userCard ( user )}
Snippets cannot use rest parameters (...rest). Each parameter must be explicitly named.
Snippet Scope
Snippets can reference values from their surrounding context:
< script >
let { message = `it's great to see you!` } = $ props ();
</ script >
{# snippet hello ( name )}
< p > hello { name } ! { message } ! </ p >
{/ snippet }
{@ render hello ( 'alice' )}
{@ render hello ( 'bob' )}
Snippets are visible to siblings and children:
< div >
{# snippet x ()}
{# snippet y ()}...{/ snippet }
<!-- This works -->
{@ render y ()}
{/ snippet }
<!-- This errors - y is not in scope -->
{@ render y ()}
</ div >
<!-- This also errors - x is not in scope -->
{@ render x ()}
Recursive Snippets
Snippets can reference themselves:
{# snippet countdown ( n )}
{# if n > 0 }
< span > { n } ... </ span >
{@ render countdown ( n - 1 )}
{: else }
{@ render blastoff ()}
{/ if }
{/ snippet }
{# snippet blastoff ()}
< span > 🚀 </ span >
{/ snippet }
{@ render countdown ( 10 )}
Passing Snippets to Components
As Explicit Props
Pass snippets like any other prop:
<!-- App.svelte -->
< script >
import Table from './Table.svelte' ;
const fruits = [
{ name: 'apples' , qty: 5 , price: 2 },
{ name: 'bananas' , qty: 10 , price: 1 },
{ name: 'cherries' , qty: 20 , price: 0.5 }
];
</ script >
{# snippet header ()}
< th > fruit </ th >
< th > qty </ th >
< th > price </ th >
< th > total </ th >
{/ snippet }
{# snippet row ( d )}
< td > { d . name } </ td >
< td > { d . qty } </ td >
< td > { d . price } </ td >
< td > { d . qty * d . price } </ td >
{/ snippet }
< Table data = { fruits } { header } { row } />
As Implicit Props
Snippets declared inside component tags become props automatically:
<!-- Semantically identical to above -->
< Table data = { fruits } >
{# snippet header ()}
< th > fruit </ th >
< th > qty </ th >
< th > price </ th >
< th > total </ th >
{/ snippet }
{# snippet row ( d )}
< td > { d . name } </ td >
< td > { d . qty } </ td >
< td > { d . price } </ td >
< td > { d . qty * d . price } </ td >
{/ snippet }
</ Table >
The Children Snippet
Content that isn’t a snippet declaration becomes the children snippet:
<!-- App.svelte -->
< Button > click me </ Button >
<!-- Button.svelte -->
< script >
let { children } = $ props ();
</ script >
< button > {@ render children ()} </ button >
Don’t have a prop named children if your component also has content inside its tags.
Optional Snippets
Make snippets optional with optional chaining or if blocks:
Optional Chaining < script >
let { children } = $ props ();
</ script >
{@ render children ?.()}
Fallback Content < script >
let { children } = $ props ();
</ script >
{# if children }
{@ render children ()}
{: else }
< p > Default content </ p >
{/ if }
TypeScript Support
Type snippets using the Snippet interface:
< script lang = "ts" >
import type { Snippet } from 'svelte' ;
interface Props {
data : any [];
children : Snippet ;
row : Snippet <[ any ]>;
}
let { data , children , row } : Props = $ props ();
</ script >
With generics for type safety:
< script lang = "ts" generics = " T " >
import type { Snippet } from 'svelte' ;
let {
data ,
children ,
row
} : {
data : T [];
children : Snippet ;
row : Snippet <[ T ]>;
} = $ props ();
</ script >
Real-World Use Cases
Data Table <!-- Table.svelte -->
< script >
let { data , header , row } = $ props ();
</ script >
< table >
< thead >
< tr > {@ render header ()} </ tr >
</ thead >
< tbody >
{# each data as item }
< tr > {@ render row ( item )} </ tr >
{/ each }
</ tbody >
</ table >
Card Layout <!-- Card.svelte -->
< script >
let { title , children , footer } = $ props ();
</ script >
< div class = "card" >
{# if title }
{@ render title ()}
{/ if }
< div class = "body" >
{@ render children ()}
</ div >
{# if footer }
< div class = "footer" >
{@ render footer ()}
</ div >
{/ if }
</ div >
Modal Dialog <!-- Modal.svelte -->
< script >
let { header , children , actions } = $ props ();
let { open = $ bindable ( false ) } = $ props ();
</ script >
{# if open }
< div class = "modal" >
< div class = "header" >
{@ render header ()}
</ div >
< div class = "content" >
{@ render children ()}
</ div >
< div class = "actions" >
{@ render actions ?.()}
</ div >
</ div >
{/ if }
List with Empty State <!-- List.svelte -->
< script >
let { items , item , empty } = $ props ();
</ script >
{# if items . length > 0 }
< ul >
{# each items as data }
< li > {@ render item ( data )} </ li >
{/ each }
</ ul >
{: else if empty }
{@ render empty ()}
{: else }
< p > No items </ p >
{/ if }
Exporting Snippets
Export snippets from <script module> for use in other components:
<!-- math-snippets.svelte -->
< script module >
export { add , multiply };
</ script >
{# snippet add ( a , b )}
{ a } + { b } = { a + b }
{/ snippet }
{# snippet multiply ( a , b )}
{ a } × { b } = { a * b }
{/ snippet }
<!-- App.svelte -->
< script >
import { add , multiply } from './math-snippets.svelte' ;
</ script >
{@ render add ( 5 , 3 )}
{@ render multiply ( 4 , 7 )}
Snippet exports require Svelte 5.5.0 or newer. Exported snippets cannot reference non-module <script> declarations.
Migration from Slots
Snippets replace Svelte 4 slots:
Svelte 4 (Slots)
Svelte 5 (Snippets)
<!-- Button.svelte -->
< button >
< slot />
</ button >
<!-- App.svelte -->
< Button >
Click me
</ Button >