S SvelteKurs
M3 · Props & Kommunikation

Snippets & @render

Snippets sind wiederverwendbare Markup-Bausteine — sie ersetzen die alten Slots und lassen sich sogar als Props übergeben.

Was ist ein Snippet?

Ein Snippet ist ein benanntes Stück Markup, das du an einer Stelle definierst und an beliebig vielen Stellen mit {@render} einfügst — optional mit Argumenten. Das spart Wiederholung innerhalb einer Komponente.

Gruesse.svelte svelte
<script lang="ts">
  let namen = ['Anna', 'Bob', 'Carla'];
</script>

<!-- Snippet definieren: wiederverwendbares Stück Markup mit Argument -->
{#snippet gruss(name)}
  <li>Hallo, <strong>{name}</strong>!</li>
{/snippet}

<ul>
  {#each namen as n}
    {@render gruss(n)}   <!-- Snippet aufrufen -->
  {/each}
</ul>

{#snippet name(arg)}…{/snippet} definiert, {@render name(arg)} rendert. Ein Snippet kann mehrere Argumente nehmen — genau wie eine Funktion.

Die children-Prop: Ersatz für den Default-Slot

Der Inhalt, den eine Eltern-Komponente zwischen die Tags eines Kindes schreibt, landet automatisch in einer speziellen Prop namens children. Du renderst sie mit {@render children()} — das ist der Nachfolger von <slot />.

Karte.svelte svelte
<script lang="ts">
  import type { Snippet } from 'svelte';

  interface Props {
    children: Snippet;   // der Inhalt zwischen den Tags
  }

  let { children }: Props = $props();
</script>

<div class="karte">
  {@render children()}
</div>
Seite.svelte svelte
<script lang="ts">
  import Karte from './Karte.svelte';
</script>

<!-- Alles zwischen den Tags landet in der children-Prop -->
<Karte>
  <h3>Titel</h3>
  <p>Beliebiger Inhalt.</p>
</Karte>

🛤️ Rails-Vergleich: yield, content_for & Partial-Blöcke

{@render children()} entspricht dem yield in einem Rails-Layout. Benannte Snippet-Props funktionieren wie content_for, und ein Snippet mit Argument ähnelt einem Partial, das mit render layout: … do |x| einen Block bekommt.

Rails erb
<%# yield entspricht der children-Prop %>
<%# app/views/layouts/application.html.erb %>
<div class="karte"><%= yield %></div>

<%# content_for / benannter Block ~ benannte Snippet-Prop %>
<% content_for :header do %>
  <h1>Titel</h1>
<% end %>

<%# Partial mit Block ~ Snippet mit Argument %>
<%= render layout: "zeile" do |item| %>
  <%= item.name %>
<% end %>

Snippets als Props übergeben

Snippets sind Werte — du kannst sie also wie jede andere Prop an ein Kind reichen. So bestimmt die Eltern-Komponente, wie das Kind einzelne Teile rendert. Ein Snippet, das du direkt zwischen den Tags mit passendem Namen definierst, wird automatisch zur gleichnamigen Prop.

Liste.svelte svelte
<script lang="ts">
  import type { Snippet } from 'svelte';

  interface Props {
    items: string[];
    row: Snippet<[string]>;   // Snippet mit einem string-Argument
  }

  let { items, row }: Props = $props();
</script>

<ul>
  {#each items as item}
    {@render row(item)}
  {/each}
</ul>
App.svelte svelte
<Liste items={namen}>
  {#snippet row(name)}
    <li class="fett">{name}</li>
  {/snippet}
</Liste>

<!-- Ein Snippet, das direkt als Attribut übergeben ist, wird zur Prop 'row'. -->

💡 Typisierung

Der Typ Snippet kommt aus svelte. Argumente gibst du als Tupel an: Snippet<[string]> ist ein Snippet mit einem string-Argument, Snippet ohne eckige Klammern nimmt keine Argumente.

Vergleich zu früheren Slots

Wenn du Svelte-4-Code kennst: Snippets ersetzen das komplette Slot-System. Ein Mapping macht die Umstellung leicht.

svelte
<!-- ❌ Svelte 4: slots -->
<slot />                        <!-- Default-Inhalt -->
<slot name="header" />          <!-- benannter Slot -->
<slot item={x} />               <!-- Slot-Prop -->

<!-- ✅ Svelte 5: snippets -->
{@render children()}            <!-- children-Prop -->
{@render header()}              <!-- benannte Snippet-Prop -->
{@render item(x)}               <!-- Snippet mit Argument -->

Live: Liste mit lokalem Snippet

Snippets funktionieren komplett innerhalb einer Datei — deshalb können wir sie hier live zeigen. Das Snippet zeile bekommt eine Aufgabe als Argument und wird pro Listeneintrag gerendert:

▶ render in einer Liste · Interaktiv
  • Props-Lektion lesen
  • Snippets ausprobieren hoch
  • Kaffee holen

Dasselbe Snippet zeile rendert jeden Eintrag — Markup einmal, Aufruf pro Zeile.

Zusammenfassung

💡 Das Wichtigste

  • {#snippet name(arg)}…{/snippet} definiert, {@render name(arg)} rendert.
  • Inhalt zwischen den Tags landet in der children-Prop.
  • Snippets sind Werte und lassen sich als Props übergeben (Typ Snippet<[…]>).
  • Snippets ersetzen die alten <slot>-Mechanismen vollständig.

🎯 Probier es selbst

Ergänze die Demo um ein zweites Snippet badge(text), das ein kleines Label rendert, und rufe es innerhalb von zeile für die Priorität auf. So siehst du, dass Snippets sich gegenseitig aufrufen können.