Neben Form- und Media-Bindings bietet Svelte einige weitere Bindings, mit denen sich DOM-Referenzen, Element-Größen und Spezial-Elemente wie <details> oder contenteditable-Bereiche elegant ansprechen lassen. Dieser Artikel zeigt bind:this, alle Größen-Bindings (intern via ResizeObserver) und die Spezialfälle für details/contenteditable.

bind:this – Referenz auf das DOM-Element

bind:this speichert die Referenz auf den DOM-Knoten in einer Variable — analog zu Reacts useRef:

svelte Focus auf Input
<script>
    let input;

    function focusInput() {
        input?.focus();
    }
</script>

<input bind:this={input} />
<button onclick={focusInput}>Fokussieren</button>

Wichtig: Die Variable ist erst nach dem Mount gesetzt. Vor dem ersten Render ist sie undefined — Optional-Chaining (input?.focus()) verhindert Fehler.

Mit TypeScript

svelte Typisierte Refs
<script lang="ts">
    let input: HTMLInputElement;
    let canvas: HTMLCanvasElement;
    let video: HTMLVideoElement;
</script>

Größen-Bindings (Read-only)

Auf jedem HTML-Element verfügbar — die Werte werden über einen internen ResizeObserver versorgt und bleiben automatisch aktuell:

BindingWert-TypBeschreibung
bind:clientWidthnumberSichtbare Breite ohne Scrollbar/Border
bind:clientHeightnumberSichtbare Höhe
bind:offsetWidthnumberAußenbreite inkl. Border
bind:offsetHeightnumberAußenhöhe
bind:contentRectDOMRectReadOnlyDOMRect aus dem ResizeObserver
bind:contentBoxSizeArrayContent-Box-Maße
bind:borderBoxSizeArrayBorder-Box-Maße
bind:devicePixelContentBoxSizeArrayPixel-genaue Content-Box
svelte Responsive nach Größe
<script>
    let width = $state(0);
    let isCompact = $derived(width < 600);
</script>

<div bind:clientWidth={width} class:compact={isCompact}>
    <p>Container: {width}px breit</p>
    {#if isCompact}
        <p>Kompakte Ansicht</p>
    {:else}
        <p>Standard-Ansicht</p>
    {/if}
</div>

contentRect für mehr Details

bind:contentRect liefert ein vollständiges DOMRectReadOnly-Objekt:

svelte contentRect
<script>
    let rect = $state(null);
</script>

<div bind:contentRect={rect}>
    Inhalt …
</div>

{#if rect}
    <p>{rect.width.toFixed(0)} × {rect.height.toFixed(0)}</p>
{/if}

bind:open für <details>

<details> hat einen aufklappbaren Zustand — bind:open macht ihn reaktiv:

svelte details-Toggle
<script>
    let isOpen = $state(false);
</script>

<details bind:open={isOpen}>
    <summary>FAQ-Eintrag</summary>
    <p>Antwort …</p>
</details>

<p>Aktuell: {isOpen ? 'aufgeklappt' : 'eingeklappt'}</p>
<button onclick={() => isOpen = !isOpen}>Toggle</button>

Contenteditable-Bindings

Wenn ein Element contenteditable ist, lassen sich seine Inhalte mit drei verschiedenen Bindings synchronisieren:

BindingLiefert/Empfängt
bind:innerHTMLHTML-Markup
bind:innerTextSichtbarer Text (mit Whitespace)
bind:textContentRoher Text-Inhalt
svelte Inline-Editor
<script>
    let html = $state('<strong>Klick</strong> mich an, um zu editieren.');
</script>

<div contenteditable="true" bind:innerHTML={html}></div>

<hr />

<pre>{html}</pre>

Beim Tippen wird html aktualisiert. Setzt der Code html = '...', ändert sich auch der Editor-Inhalt.

Vorsicht: contenteditable-HTML kann beliebige Tags enthalten. Bei Speicherung sanitizen.

Praxis-Beispiel: Container mit responsivem Layout

svelte ResponsiveCard.svelte
<script>
    let { children } = $props();

    let width = $state(0);

    let layout = $derived(
        width < 480 ? 'narrow' :
        width < 768 ? 'medium' : 'wide'
    );
</script>

<article bind:clientWidth={width} class={`card layout-${layout}`}>
    {@render children()}
</article>

<style>
    .card { padding: 1rem; border: 1px solid #ddd; }
    .layout-narrow { font-size: 0.9em; }
    .layout-wide { padding: 2rem; }
</style>

Die Komponente reagiert auf ihre eigene Container-Breite — ohne Window-Listener, ohne CSS-Container-Queries. Funktioniert in jedem Layout-Kontext.

Praxis-Beispiel: Canvas mit Auto-Resize

svelte ResponsiveCanvas.svelte
<script>
    let canvas;
    let width = $state(0);
    let height = $state(0);

    $effect(() => {
        if (!canvas || width === 0) return;
        canvas.width = width;
        canvas.height = height;

        const ctx = canvas.getContext('2d');
        ctx.fillStyle = 'teal';
        ctx.fillRect(0, 0, width, height);
    });
</script>

<div bind:clientWidth={width} bind:clientHeight={height} style="height: 200px">
    <canvas bind:this={canvas}></canvas>
</div>

bind:clientWidth und bind:clientHeight reagieren auf Layout-Änderungen — der Canvas wird automatisch neu skaliert und gezeichnet.

Häufige Stolperfallen

bind:this zu früh nutzen. Im <script>-Top-Level ist die Variable undefined — sie wird erst beim Mount belegt. Mit $effect(() => { if (input) input.focus(); }) arbeiten oder Optional-Chaining nutzen.

Größen-Bindings auf inline-Elementen. Bei display: inline haben viele Browser keine sinnvolle Höhe — der Wert kann 0 bleiben. Lieber auf Block- oder Flex-Elemente binden.

bind:contentRect synchron im <script> lesen. Direkt nach Mount ist der Wert noch null. Im $effect mit Null-Check arbeiten.

Zwei Bindings auf demselben Wert kollidieren. Mehrere Größen-Bindings sind okay (jedes liefert seinen eigenen Wert). Ein bind:innerHTML und bind:textContent gleichzeitig führt zu Konflikten — nur eines verwenden.

bind:innerHTML ohne contenteditable. Ohne das Attribut ist das Element nicht editierbar — Svelte schreibt zwar den Inhalt, aber der Nutzer kann nicht eingeben.

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Bindings

Zur Übersicht