Snippets and Content
Props pass data into a child; content passes markup. Svelte 5's mechanism is the children snippet plus the {#snippet} block — its replacement for the old <slot> system, covering React's children, Vue's slots, and Angular's <ng-content> all at once. It's the most distinctive of the four frameworks' approaches, and worth taking slowly.
The Default children Snippet
Whatever a parent writes between a component's tags becomes a special prop called children — a snippet (a reusable chunk of markup). The child renders it with {@render children()}. So children is React's {children}, but instead of just embedding it, you call it via {@render} — because a snippet is technically a renderable function. Card doesn't know what's inside; it just renders whatever it's handed.
{#snippet name()}...{/snippet} defines a chunk of markup, and {@render name()} renders one. The default children snippet (the content between tags) is just the most common case. Everything in this chapter is built from these two primitives.
Named Snippets — Multiple Insertion Points
For several insertion points, the parent defines named snippets with {#snippet header()}...{/snippet} inside the component tags — and they arrive as props of those names. Anything not in a named snippet becomes the default children. This is the equivalent of Vue's named slots and React's named-JSX-props approach, expressed through the snippet system.
Fallback Content
Because snippets are just props (a value, or undefined if not passed), fallback content is a plain {#if} check — render the snippet if it exists, otherwise show a default. More explicit than Vue's "put fallback inside the slot tag," but using only tools you already know.
Parameterised Snippets — Passing Data Back
The most powerful case: a snippet can take parameters. The child calls {@render row(item)}, passing data out to the markup the parent provided; the parent's {#snippet row(person)} receives it. List owns the looping and data; the parent decides exactly how each row looks. This is the direct equivalent of React's render props and Vue's scoped slots — and notably, it's the same snippet syntax as the simpler cases, not a separate feature.
children for simple content, named props for multi-region layouts, and render props for "pass data to the caller's markup." Svelte 5's snippets do all three with one consistent primitive — and snippets can even be defined and reused within a single component (a chunk of repeated markup rendered in several places), which the others can't do as cleanly.
{@render name()} (with parentheses — it's a call), not embedded like a value. And Svelte 4's <slot> / <slot name="x"> / let: system is removed in Svelte 5 — snippets replace all of it. If you see <slot> in a tutorial, that's pre-v5 code.
| Svelte 5 | React | Vue | Angular |
|---|---|---|---|
| children + {@render} | {children} | default <slot> | <ng-content> |
| named snippets | named JSX props | named slots | <ng-content select> |
| parameterised snippet | render props | scoped slots | template context |
| reuse a snippet in-component | — (extract a component) | — | — |
Coding Challenges
Build a Card component that renders its children snippet inside a styled div, then use it twice with completely different inner markup. Add a {#if children} fallback shown when no content is passed.
📄 View solutionBuild a Panel component with header and footer named snippets plus the default children for the body, and fill all three from a parent using {#snippet header()} / default content / {#snippet footer()}.
📄 View solutionBuild a List component that takes an items array and a row snippet, looping over the items and calling {@render row(item)} for each. In the parent, define {#snippet row(person)} to render each item your own way (e.g. bold name + muted id).
📄 View solutionChapter 8 Quick Reference
- children prop + {@render children()} — content between tags (= React's
{children}) - {#snippet name()}...{/snippet} defines markup; {@render name()} renders it
- Named snippets arrive as same-named props — for multi-region layouts (= named slots)
- Fallback — a plain
{#if children}...{:else}...{/if} - Parameterised snippets (
{@render row(item)}→{#snippet row(x)}) = render props / scoped slots - One mechanism covers children, named regions, and data-passing; Svelte 4's
<slot>is removed - Next chapter: lifecycle — onMount, onDestroy, and $effect for teardown