Neben Block-Tags wie {#if} und {#each} kennt Svelte vier Special Tags, die mit @ beginnen: {@html} für rohes HTML, {@const} für lokale Block-Variablen, {@render} zum Aufrufen von Snippets und {@debug} als pragmatischer Debugging-Helfer. Sie sind syntaktisch klein, lösen aber jeweils ein eigenes Problem. Dieser Artikel zeigt jeden Tag mit Anwendungsfall.

{@html ...} – Rohes HTML rendern

Standardmäßig escaped Svelte alle Werte. Wenn du bewusst HTML aus einem String rendern willst (z. B. von einem CMS, Markdown-Renderer oder einer Rich-Text-API), gibt es {@html ...}:

svelte @html in Aktion
<script>
    let content = '<strong>Wichtig:</strong> Heute ist Montag.';
</script>

<div>{@html content}</div>

XSS-Risiko

Das @html-Tag umgeht das Auto-Escaping vollständig. Niemals Nutzer-Input direkt damit rendern — sonst öffnest du XSS-Lücken:

svelte − Gefährlich
<script>
    let userComment = $props().comment; // beliebiger User-Input
</script>

<div>{@html userComment}</div> <!-- XSS-Risiko -->

Wenn HTML aus User-Input gerendert werden muss, vorher mit DOMPurify oder einer ähnlichen Library sanitizen:

svelte + Mit Sanitizer
<script>
    import DOMPurify from 'isomorphic-dompurify';
    let { comment } = $props();
    let safe = $derived(DOMPurify.sanitize(comment));
</script>

<div>{@html safe}</div>

Typische sichere Anwendungsfälle

  • Markdown-Output aus einer trusted Build-Quelle.
  • CMS-Inhalte mit serverseitiger Sanitization.
  • Statische Konfiguration (z. B. Icon-SVGs aus eigenen Dateien).

{@const ...} – Lokale Block-Variablen

Innerhalb von {#each}-, {#if}- oder {#snippet}-Blöcken lassen sich lokale Konstanten definieren — praktisch für berechnete Werte, die nicht außerhalb des Blocks gebraucht werden:

svelte @const in {#each}
{#each products as product (product.id)}
    {@const total = product.price * product.qty}
    {@const isExpensive = total > 1000}

    <li class:expensive={isExpensive}>
        {product.name}: {total.toFixed(2)} €
    </li>
{/each}

Die Konstanten werden pro Iteration neu berechnet und sind nur innerhalb des Blocks sichtbar.

Wann sinnvoll?

  • Wiederholte Berechnung im selben Block — vermeidet Code-Duplikation.
  • Lesbarkeit — komplexe Ausdrücke bekommen einen Namen.
  • Nur lokal interessant — keine Notwendigkeit, im <script> ein eigenes $derived anzulegen.

{@render ...} – Snippet rendern

Snippets — Svelte 5s Slot-Ersatz — werden mit {@render snippet()} ausgegeben:

svelte Snippet rendern
<script>
    let { children, header } = $props();
</script>

<article>
    {@render header?.()}
    {@render children()}
</article>

Mehr zu Snippets im Artikel Snippets statt Slots.

Mit Argumenten

Snippets können Argumente entgegennehmen:

svelte Snippet mit Argument
{#snippet greet(name)}
    <p>Hallo, {name}</p>
{/snippet}

{@render greet('Anna')}
{@render greet('Bernd')}

{@debug ...} – DevTools-Pause

{@debug} setzt einen Breakpoint und loggt die übergebenen Variablen, sobald sich eine davon ändert:

svelte @debug
<script>
    let user = $state({ name: 'Anna' });
    let count = $state(0);
</script>

{@debug user, count}

<button onclick={() => count++}>+1</button>

Verhalten:

  • Bei aktivierter DevTools-Konsole: Browser pausiert beim Update (wie ein debugger;-Statement).
  • Werte werden geloggt — du siehst, wie sich der State entwickelt.

{@debug} mit leeren Klammern triggert bei jeder Update-Phase:

svelte Bei jedem Render pausieren
{@debug}

In Production-Builds wird {@debug} automatisch entfernt — du kannst es im Code lassen.

Übersicht aller Special Tags

TagZweck
{@html}Rohes HTML rendern (XSS-Risiko ohne Sanitization)
{@const}Lokale Konstante in einem Block
{@render}Snippet aufrufen und rendern
{@debug}Logging und Pause in DevTools (Dev-only)

Häufige Stolperfallen

@html mit Nutzer-Input ohne Sanitization. Klassische XSS-Lücke. Immer sanitizen oder Markup vermeiden.

@const außerhalb eines Blocks. Funktioniert nur in {#each}, {#if}, {#snippet}. Im Top-Level einer Komponente nutzt man stattdessen let oder $derived.

@render für eine Komponente verwendet. {@render} ist nur für Snippets gedacht — nicht für Komponenten. Komponenten werden weiterhin als <MyComponent /> gerendert.

@debug in Production angeklickt. Wird im Production-Build automatisch entfernt; in Development pausiert es den Browser, was Tests blockieren kann. In CI-Umgebungen entfernen.

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Template-Syntax

Zur Übersicht