@property für typisierte Custom Properties mit Tailwind CSS kombinieren
AI generated
tw
Tailwind CSS · CSS @property · Animation
@property für typisierte Custom Properties
Animierbare CSS-Variablen mit typisierten Werten in Kombination mit Tailwind CSS

Klassische CSS-Custom-Properties sind reine Zeichenketten ohne Typ, weshalb der Browser sie nicht animieren kann, selbst wenn der Wert wie eine Zahl oder ein Winkel aussieht. Mit der @property-Regel lassen sich Custom Properties dagegen mit einem echten Syntax-Typ, einem Vererbungsverhalten und einem Initialwert registrieren, wodurch sie plötzlich animierbar werden. Dieser Artikel zeigt, wie sich @property sinnvoll mit Tailwind CSS kombinieren lässt, mit einem praktischen Beispiel für eine animierte Gradient-Winkel-Rotation.

14 Min. Lesezeit @property · Typisierte Variablen Animierbare Gradient-Winkel

1. Warum klassische Custom Properties nicht animierbar sind

Eine klassische CSS-Custom-Property, deklariert über --winkel: 45deg, ist für den Browser intern nichts weiter als eine Zeichenkette. Der Browser interpretiert diesen Wert erst dort, wo die Property tatsächlich per var() eingesetzt wird, etwa in transform: rotate(var(--winkel)). Bis zu diesem Einsatzpunkt weiß der Browser nicht, ob es sich um einen Winkel, eine Farbe oder eine beliebige andere CSS-Syntax handelt, und genau das macht eine Animation dieser Property unmöglich, denn Animation setzt voraus, dass der Browser zwischen zwei Werten sinnvoll interpolieren kann.

Ohne einen bekannten Typ kann der Browser bei einer Transition von --winkel: 0deg zu --winkel: 360deg nicht wissen, dass er stufenlos zwischen den beiden Winkelwerten interpolieren soll. Stattdessen springt der Wert bei einer klassischen Custom Property abrupt vom alten zum neuen Wert, ganz ohne die Zwischenschritte, die eine sichtbare Animation ausmachen würden. Genau diese Lücke schließt die @property-Regel, indem sie der Custom Property einen echten, vom Browser verstandenen Typ zuweist.

2. Die Syntax der @property-Regel im Detail

Eine @property-Registrierung besteht aus drei Pflichtfeldern: syntax definiert den erlaubten Werttyp, zum Beispiel <angle> für Winkel, <color> für Farben oder <length> für Längenangaben. inherits legt fest, ob die Property an Kindelemente vererbt wird, und initial-value definiert den Wert, der gilt, wenn die Property nirgends explizit gesetzt wurde. Alle drei Felder sind zwingend erforderlich, eine @property-Regel ohne eines der drei Felder wird vom Browser als ungültig verworfen und ignoriert.

Die Registrierung selbst steht als eigenständiger At-Rule-Block im Stylesheet, unabhängig von einem bestimmten Selektor, ähnlich wie @font-face oder @keyframes. Der Property-Name in der @property-Regel und der Name, mit dem die Property später per var() verwendet wird, müssen exakt übereinstimmen, inklusive der beiden führenden Bindestriche, da CSS Custom Properties grundsätzlich case-sensitiv behandelt.


@property --gradient-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.rotating-border {
  background: conic-gradient(from var(--gradient-angle), #6366f1, #ec4899, #6366f1);
}

3. Vorteile der Typisierung über reine Interpolation hinaus

Der offensichtlichste Vorteil ist die Animierbarkeit, aber die Typisierung bringt noch zwei weitere praktische Verbesserungen mit sich. Erstens validiert der Browser Werte gegen den deklarierten syntax-Typ: Wird versucht, einer als <angle> typisierten Property ein ungültiger Wert wie eine Zeichenkette zuzuweisen, verwirft der Browser diesen Wert und fällt auf den initial-value zurück, statt den fehlerhaften Wert stillschweigend als Zeichenkette zu übernehmen, wie es bei einer klassischen Custom Property passieren würde.

Zweitens lässt sich über inherits: false gezielt verhindern, dass eine Property ungewollt von Kindelementen übernommen wird, was bei klassischen Custom Properties, die immer vererben, gelegentlich zu überraschendem Verhalten führt, etwa wenn ein verschachteltes Element plötzlich denselben Gradient-Winkel wie sein Elternelement zeigt, obwohl dafür kein eigener Wert gesetzt wurde. Für lokale, komponenten-gebundene Werte wie einen Animations-Zwischenzustand ist inherits: false fast immer die richtige Wahl.

4. Animierbare Custom Properties am Beispiel Gradient-Winkel

Ein konkretes Beispiel, bei dem eine typisierte Custom Property den entscheidenden Unterschied macht, ist die Animation des Winkels in einem conic-gradient(). Ohne @property lässt sich ein rotierender Farbverlauf-Rand nur über eine @keyframes-Regel realisieren, die den kompletten background-Wert mit fest kodierten Zwischenwinkeln definiert, was unflexibel ist und sich schlecht mit dynamisch berechneten Start- oder Endwinkeln kombinieren lässt.

Mit einer als <angle> typisierten Property lässt sich stattdessen einfach eine transition oder @keyframes-Animation auf die Custom Property selbst legen, und der Browser interpoliert automatisch jeden Zwischenwinkel zwischen Start- und Zielwert. Das reduziert die Animation auf eine einzige animierte Eigenschaft, während die eigentliche Gradient-Deklaration unverändert bleibt und lediglich per var() auf den aktuellen, sich verändernden Winkel verweist.


@property --gradient-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@keyframes rotate-gradient {
  to {
    --gradient-angle: 360deg;
  }
}

.rotating-border {
  background: conic-gradient(from var(--gradient-angle), #6366f1, #ec4899, #6366f1);
  animation: rotate-gradient 4s linear infinite;
}

5. Integration in Tailwind CSS v4

Tailwind CSS v4 setzt intern selbst auf @property, unter anderem für einige der eingebauten Gradient- und Transform-Utilities, um deren Zwischenwerte animierbar zu machen. Für eigene typisierte Custom Properties bietet sich in Tailwind v4 die zentrale CSS-Datei mit der @theme-Direktive an, in der neben Design-Tokens auch beliebige weitere @property-Registrierungen stehen können, sodass die Typisierung an derselben Stelle liegt wie die restliche Tailwind-Konfiguration.

Der eigentliche Zugriff auf die typisierte Property innerhalb eines Utility-Kontexts läuft über Tailwinds Arbitrary-Value-Syntax, etwa bg-[conic-gradient(from_var(--gradient-angle),theme(colors.indigo.500),theme(colors.pink.500))], oder pragmatischer über eine eigene Komponentenklasse, die per @apply oder direktem CSS die Gradient-Deklaration kapselt. Für Animationen, die per Alpine.js oder JavaScript gesteuert werden, lässt sich der aktuelle Winkel zusätzlich über ein Inline-style-Attribut mit --gradient-angle: 120deg direkt am Element setzen, ganz ohne Tailwind-Klasse dafür zu benötigen.

6. Die Feinheiten von inherits und initial-value

Der inherits-Flag hat einen Effekt, der über reine Vererbung hinausgeht: Bei inherits: false setzt der Browser die Property bei jedem Element, das keinen expliziten Wert dafür gesetzt hat, konsequent auf den initial-value zurück, unabhängig davon, welcher Wert am Elternelement galt. Bei inherits: true dagegen wird der Wert des Elternelements übernommen, genau wie bei einer klassischen Custom Property. Für animierte Zustände, die pro Element unabhängig sein sollen, ist inherits: false fast immer die richtige Wahl.

initial-value muss dabei ein gültiger Wert für den deklarierten syntax-Typ sein, sonst wird die komplette @property-Regel als ungültig verworfen, nicht nur das fehlerhafte Feld. Eine @property-Registrierung mit syntax: "<angle>" und initial-value: 0 ohne Einheit ist deshalb ungültig, da ein Winkel-Wert stets eine Einheit wie deg, rad oder turn benötigt. Dieser strenge Validierungsmechanismus verhindert stille Fehler, erzeugt bei einem Tippfehler aber auch keine Fehlermeldung in der Konsole, sondern lässt die Property einfach ungenutzt.

7. Browser-Support und Fallback-Strategie

Die @property-Regel wird von allen aktuellen Versionen von Chrome, Edge und Safari unterstützt, Firefox zog mit vollständiger Unterstützung ab Version 128 nach, sodass die Funktion inzwischen als produktionsreif für die meisten Projekte gilt. Für Projekte, die noch ältere Firefox-Versionen unterstützen müssen, verhält sich eine nicht registrierte Custom Property weiterhin wie eine klassische, untypisierte Property, das Layout bricht also nicht, die Animation der Property selbst funktioniert nur eben nicht.

Eine robuste Fallback-Strategie kombiniert deshalb einen statischen, nicht animierten Zustand als Basiswert mit einer über @supports abgesicherten Animation, die nur in Browsern mit @property-Unterstützung aktiviert wird. So sieht das Element in älteren Browsern weiterhin passend aus, nur eben ohne die Rotation, statt in einem kaputten oder unerwarteten Zustand zu landen. Die Prüfung erfolgt über @supports (background: paint(something)) oder direkter über eine Feature-Detection auf @property selbst, je nach gewünschtem Detailgrad der Absicherung.


.rotating-border {
  background: conic-gradient(from 0deg, #6366f1, #ec4899, #6366f1);
}

@supports (background: paint(something)) {
  @property --gradient-angle {
    syntax: "<angle>";
    inherits: false;
    initial-value: 0deg;
  }

  .rotating-border {
    background: conic-gradient(from var(--gradient-angle), #6366f1, #ec4899, #6366f1);
    animation: rotate-gradient 4s linear infinite;
  }
}

8. Praxisbeispiel: ein animierter Button-Rand mit Tailwind

Ein häufiger Anwendungsfall ist ein Call-to-Action-Button mit einem sanft rotierenden Farbverlauf als Rand, der bei einem primären Button die Aufmerksamkeit lenken soll, ohne aufdringlich zu wirken. Der Trick besteht darin, den Button-Hintergrund und den animierten Gradient-Rand über zwei gestapelte Ebenen zu realisieren: eine äußere Ebene mit dem animierten conic-gradient() als Hintergrund und eine leicht kleinere innere Ebene mit dem eigentlichen Button-Hintergrund, sodass nur ein schmaler Streifen des äußeren Gradients als Rand sichtbar bleibt.

In Tailwind-Klassen umgesetzt bedeutet das ein relativ positioniertes äußeres Element mit der typisierten Custom Property und der Animation, sowie ein absolut positioniertes inneres Element mit inset-0.5 und der eigentlichen Button-Hintergrundfarbe, das den größten Teil der äußeren Fläche überdeckt. Die Textklasse und der Klick-Handler für den Button liegen dabei auf dem inneren Element, damit der animierte Rand rein dekorativ bleibt und keine eigene Interaktionsfläche beansprucht.

9. Grenzen und typische Stolperfallen

Eine häufige Falle ist, den syntax-Typ zu allgemein zu wählen, etwa syntax: "*", was zwar jeden beliebigen Wert erlaubt, dabei aber genau die Typsicherheit und Animierbarkeit wieder aufgibt, die @property überhaupt erst rechtfertigt. Für eine animierbare Property ist immer ein konkreter Typ wie <angle>, <length>, <color> oder <number> nötig, ein generischer Wildcard-Typ verhält sich im Hinblick auf Animation genauso wie eine klassische, untypisierte Custom Property.

Eine zweite Stolperfalle betrifft die Registrierung selbst innerhalb komponentenbasierter Build-Systeme: Wird dieselbe @property-Regel versehentlich mehrfach mit unterschiedlichen syntax-Werten im Projekt registriert, etwa weil zwei unabhängige Komponenten denselben Property-Namen wiederverwenden, gewinnt je nach Browser die zuletzt geladene Definition, was zu inkonsistentem Verhalten zwischen Entwicklungs- und Produktionsumgebung führen kann. Ein zentraler Ort für alle @property-Registrierungen, etwa direkt neben der Tailwind-@theme-Definition, beugt diesem Problem zuverlässig vor.

Feld Pflicht Beispielwert Effekt
syntax ja "<angle>" Definiert den erlaubten Werttyp und ermöglicht Interpolation
inherits ja false Steuert, ob Kindelemente den Wert ohne eigene Deklaration übernehmen
initial-value ja 0deg Wert, der ohne explizite Zuweisung oder bei ungültigem Wert gilt
@supports-Fallback empfohlen @supports (background: paint(something)) Statischer Zustand für Browser ohne @property-Unterstützung

Mironsoft

Tailwind-CSS-Architektur, Design-Systeme und Performance

Tailwind-Frontends, die trotz tausender Utility-Klassen wartbar bleiben?

Wir prüfen bestehende Tailwind-Projekte auf aufgeblähte Klassenlisten, inkonsistente Design-Tokens und ungenutzte CSS-Reste und bauen daraus ein Design-System, das sich sauber skaliert statt mit jeder Komponente unübersichtlicher zu werden.

Design-System-Review

Tokens, Spacing-Skala und Komponentenkonsistenz auf Wartbarkeit prüfen.

Performance-Optimierung

CSS-Bundle-Größe, Purge-Konfiguration und Ladezeiten systematisch reduzieren.

Component-Architektur

Wiederverwendbare, gut strukturierte Komponenten statt Klassenlisten-Wildwuchs aufbauen.

10. Zusammenfassung

@property mit Tailwind: Das Wichtigste auf einen Blick

Kernidee

@property gibt einer Custom Property einen echten Typ, wodurch der Browser zwischen Werten interpolieren und die Property animieren kann.

Pflichtfelder

syntax, inherits und initial-value müssen alle drei gesetzt sein, sonst wird die gesamte Registrierung als ungültig verworfen.

Praxisbeispiel

Ein animierter conic-gradient()-Winkel für rotierende Button-Ränder, mit klassischen Custom Properties nicht animierbar.

Fallback

Statischer, nicht animierter Grundzustand außerhalb von @supports, aktivierte Animation nur in unterstützenden Browsern.

11. FAQ: @property mit Tailwind: Das Wichtigste auf einen Blick

1Warum kann eine klassische CSS-Custom-Property nicht animiert werden?
Weil der Browser sie intern als reine Zeichenkette ohne Typ behandelt und deshalb nicht weiß, wie zwischen zwei Werten sinnvoll interpoliert werden soll.
2Welche Felder sind bei @property zwingend erforderlich?
syntax, inherits und initial-value. Fehlt eines der drei Felder, verwirft der Browser die komplette Registrierung als ungültig.
3Wofür steht der syntax-Typ bei @property?
Er definiert den erlaubten Werttyp der Property, zum Beispiel für Winkel oder für Farben, und ist Voraussetzung für Animierbarkeit.
4Was passiert bei inherits: false?
Kindelemente ohne eigene Deklaration erhalten immer den initial-value, unabhängig vom Wert am Elternelement, statt den Wert wie bei einer klassischen Property zu erben.
5Wie animiere ich einen Gradient-Winkel mit @property?
Indem die Custom Property als typisiert wird und anschließend per @keyframes oder transition auf genau diese Property animiert wird, während die Gradient-Deklaration selbst unverändert bleibt.
6Wie kombiniere ich @property mit Tailwind CSS v4?
Über die zentrale CSS-Datei mit der @theme-Direktive für die Registrierung, und über Arbitrary-Value-Syntax oder eigene Komponentenklassen für den Zugriff im Markup.
7Welche Browser unterstützen @property?
Chrome, Edge und Safari vollständig in aktuellen Versionen, Firefox seit Version 128. Für ältere Firefox-Versionen bleibt die Property nutzbar, nur ohne Animierbarkeit.
8Wie sichere ich @property für ältere Browser ab?
Mit einem statischen Basiswert außerhalb einer @supports-Regel und der eigentlichen Animation innerhalb von @supports (background: paint(something)) oder einer vergleichbaren Feature-Detection.
9Was passiert bei einem ungültigen initial-value?
Die komplette @property-Regel wird vom Browser als ungültig verworfen, nicht nur das fehlerhafte Feld, ohne dass eine Fehlermeldung in der Konsole erscheint.
10Warum sollte ich syntax: "*" vermeiden?
Weil ein generischer Wildcard-Typ genau die Typsicherheit und Animierbarkeit wieder aufgibt, die @property überhaupt erst bietet, und sich dann wie eine klassische untypisierte Property verhält.