Sobald Klassen oder Inline-Styles vom State abhängen, wird’s schnell hässlich: ein Ternärer hier, ein Template-Literal dort, am Ende keiner versteht das Markup mehr. Svelte hat dafür zwei kleine, aber sehr nützliche Direktiven. class:name={bedingung} schaltet eine Klasse abhängig vom Wert ein oder aus. style:property={wert} setzt einen einzelnen CSS-Wert reaktiv. Beides lässt sich auch beliebig oft am gleichen Element anwenden, ohne Strings zusammenzubauen.
class:name={bedingung} – Klassen bedingt schalten
Statt einen String zu basteln, der je nach Zustand andere Klassen enthält, schreibst du jede Klasse als eigene Direktive:
<script>
let active = $state(false);
</script>
<button
class="btn"
class:active={active}
onclick={() => active = !active}
>
Klick
</button>
<style>
.btn { padding: 0.5em 1em; }
.btn.active { background: teal; color: white; }
</style>Was hier passiert: Die Basisklasse btn ist immer am Element. Die Klasse active wird nur dann gesetzt, wenn die Variable active truthy ist. Sobald sich der State ändert, fügt Svelte die Klasse hinzu oder entfernt sie — du musst nichts manuell tun.
Shorthand, wenn Klassenname und Variable gleich heißen
<button class:active>Klick</button>Wenn der Klassen-Name identisch zum Variablen-Namen ist, sparst du dir die ={...}-Klammer. Das funktioniert wie der allgemeine Attribut-Shorthand in Svelte.
Mehrere Klassen am gleichen Element
Direktiven dürfen sich beliebig oft wiederholen. Du listest die unabhängigen Schalter einfach hintereinander:
<script>
let { variant = 'default', disabled = false, loading = false } = $props();
</script>
<button
class="btn"
class:btn-primary={variant === 'primary'}
class:btn-danger={variant === 'danger'}
class:btn-disabled={disabled}
class:btn-loading={loading}
>
<slot />
</button>Das ist deutlich lesbarer als der String-Bau, der ohne Direktive nötig wäre:
<button
class={`btn ${variant === 'primary' ? 'btn-primary' : ''} ${variant === 'danger' ? 'btn-danger' : ''} ${disabled ? 'btn-disabled' : ''}`}
>Die Direktiven-Form bleibt auch dann übersichtlich, wenn Bedingungen sich ändern oder neue dazukommen.
class:name zusammen mit class="..."
Du darfst eine statische Basis mit Direktiven kombinieren — sie überschreiben einander nicht, sondern ergänzen sich.
<button class="btn btn-large" class:active>
…
</button>Im DOM landen je nach Wert von active entweder class="btn btn-large" oder class="btn btn-large active". Der statische Teil bleibt immer.
style:property={wert} – einzelne CSS-Werte reaktiv setzen
Das gleiche Prinzip für Inline-Styles. Statt einen String zusammenzubauen, schreibst du eine Direktive pro CSS-Property.
<script>
let x = $state(0);
let y = $state(0);
</script>
<svelte:window onmousemove={(e) => { x = e.clientX; y = e.clientY; }} />
<div
class="dot"
style:left="{x}px"
style:top="{y}px"
></div>
<style>
.dot {
position: fixed;
width: 24px;
height: 24px;
background: teal;
border-radius: 999px;
pointer-events: none;
}
</style>Was die Direktive übernimmt:
- Bei jeder Wert-Änderung wird das CSS-Property auf dem DOM-Knoten aktualisiert.
- Die Einheit gehört direkt zum Wert (
{x}px,{progress}%). Svelte fügt keine automatische Einheit hinzu. - Du kannst beliebig viele
style:-Direktiven am gleichen Element kombinieren.
CSS-Variablen als Spezialfall
Die wahrscheinlich wichtigste Anwendung von style: haben wir bereits im Artikel zu CSS-Variablen gesehen — du setzt damit eine Custom Property, die das eigentliche Styling im <style>-Block dann konsumiert:
<div style:--progress="{progress}%">
<div class="fill"></div>
</div>Damit bleibt das Markup sauber von Layout-Logik, das CSS bekommt nur einen einzelnen reaktiven Wert.
Wichtige Modifier
Manchmal brauchst du !important, weil eine andere Regel die deinen überstimmt:
<div style:color|important={errorColor}>
…
</div>Der |important-Modifier macht aus dem Inline-Style einen !important. Spar dir das für echte Notfälle (Widerwillig-Override von Drittanbieter-CSS) — im eigenen Code ist es selten nötig.
Wann nimmst du was?
| Situation | Empfehlung |
|---|---|
| Klasse ein- oder ausschalten | class:name |
| Mehrere Klassen-Schalter am gleichen Element | mehrere class:-Direktiven |
| Komplette Klassen-Liste dynamisch berechnen | class={…} mit Helper (z. B. clsx) |
| Einzelne CSS-Property reaktiv setzen | style:property |
| CSS-Variable an Komponente von außen geben | style:--name |
| Statisches Inline-Style | style="…" |
Faustregel: Solange du wenige, klar benennbare Schalter hast, sind die Direktiven die lesbarste Form. Sobald du eine ganze Klassen-Liste aus Daten berechnen willst, lohnt sich ein Helfer wie clsx und das normale class={…}-Attribut.
Vergleich zur klassischen Form
Wer aus React kommt, kennt etwa className={clsx('btn', { active })}. In Svelte hast du beide Möglichkeiten — die Direktiven oder den klassischen String:
<!-- Direktiven -->
<button class="btn" class:active={isActive}>...</button>
<!-- Berechneter String -->
<button class={`btn${isActive ? ' active' : ''}`}>...</button>
<!-- Mit Helfer-Library -->
<script>
import clsx from 'clsx';
</script>
<button class={clsx('btn', { active: isActive })}>...</button>Alle drei sind gültig. Direktiven gewinnen, wenn die Klassen einzeln benannt sind und nicht aus einem Datensatz kommen. clsx gewinnt, wenn du mit Maps oder dynamischen Listen arbeitest.
Häufige Stolperfallen
Direktive und class-Attribut konkurrieren erwartet.
Tun sie nicht. Statisches class="btn" und class:active ergänzen sich. Beide landen am DOM, ohne dass die Direktive den statischen Teil überschreibt.
Einheit beim style:-Wert vergessen.
style:left={50} setzt left: 50 — der Browser ignoriert das, weil keine Einheit angegeben ist. Mit "{50}px" oder einer expliziten Einheit (50 + 'px') klappt es.
Boolean-Attribute mit class: verwechseln.
class:active={true} schaltet die Klasse ein. class:active (ohne Klammer und ohne Variable gleichen Namens) ist ein Fehler. Wenn du sie immer haben willst, gehört active einfach in die normale class="..."-Liste.
style: für komplette Style-Strings nutzen wollen.
style: setzt eine Property pro Direktive. Wer einen ganzen Block setzen will, nimmt das normale style="..."-Attribut.
Vergessen, dass class: reaktiv ist.
Sobald die referenzierte Variable mit $state reaktiv ist, aktualisiert die Klasse sich automatisch. Ist sie eine normale let-Variable, passiert nichts beim Update.