Transform

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche
Transformmit CSSdrehen,
skalieren, schräg
stellen und
verschieben

Durch CSS-Transform können Sie die Form eines HTML- oder SVG-Elements zwei- oder drei-dimensional ändern. So lässt es sich etwa spiegeln, drehen oder scheren, aber auch verschieben. Eine solche Transformation ist auf viele HTML Elemente anwendbar, mit Ausnahme von nicht ersetzten Inline-Elementen.

  1. Individuelle Eigenschaften
  2. transform-Eigenschaft
    • Transformations-Funktionen
    • Ausführungsreihenfolge
    • Transforms kombinieren
  3. Drehen, Kreisen und Pendeln
  4. SVG-Transformationen
    • transform-Attribut


  5. 3D-Transforms


Individuelle Transformations-Eigenschaften

In SVG konnte man Elemente mit dem transform-Attribut verschieben, drehen und spiegeln. Seit 2008 gab es in der CSS-Welt eine entsprechende CSS-Eigenschaft, die sogar 3D-Transformationen ermöglicht.

Im CSS Transforms Module Level 2 wurden zusätzlich die Einzeleigenschaften rotate, scale und translate eingeführt, die mittlerweile von allen Browsern unterstützt werden.[1] Mit ihnen ist es möglich, einfache Transformationen unabhängig voneinander zu festzulegen, und zwar in einer Weise, die der typischen Verwendung auf der Benutzeroberfläche entspricht, anstatt sich die Reihenfolge in transform merken zu müssen.

translate

Die translate-Eigenschaft verschiebt die Form eines HTML- oder SVG-Elements.

Sie erwartet einen, zwei oder drei Werte.

Beachten Sie: Die „neuen“ CSS-Eigenschaften folgen der gewohnten CSS-Syntax:
  • translate erfordert ein, zwei oder drei mit Leerzeichen getrennte Werte ohne umschließende Klammern.
  • die gleichlautende translate()-Funktion erfordert dagegen zwei kommaseparierte Werte innerhalb der Klammer.


Verschiebung eines HTML-Elements ansehen …
@keyframes translating {
  0%  { translate: 0    0;}
  25% { translate:  0;}
  50% { translate: 20em 200px;}
  75% { translate: 0    200px;}
  100%{ translate: 0    0;}
}
.animiert {
    animation: translating 4s linear infinite;
	background: #dfac20;
}

Im Beispiel wird das aside-Element mit der CSS-animation translating zuerst nach rechts, dann nach unten, nach links und dann wieder hoch zum Ausgangspunkt verschoben. Dabei wird der folgende Textabsatz kurzfristig verdeckt.

Beachten Sie: Ein transformiertes Element wird nicht aus dem Elementfluss entfernt. Der Browser reserviert Platz für das Element, so als würde keine Transformation vorliegen. An der Position, an die das Element durch die Transformation bewegt wird, reserviert er dagegen keinen Platz. Statt dessen wird für das Element ein neuer Stapelkontext erstellt, so dass es - sofern kein z-index gesetzt wird - über den Inhalt am Zielpunkt gelegt wird.

Für Effekte wie :hover verhält sich das Element zunächst so, als befände es sich noch an seiner Ausgangsposition. Das klingt merkwürdig, aber andernfalls würde ein :hover-Effekt, der das Element an eine andere Stelle schiebt, eventuell sofort den Effekt beenden und das Element hin und her flackern lassen. Erst dann, wenn die Maus in den Bereich kommt, den das Element an seiner Zielposition belegt, wird der Auslösebereich für :hover auf die Zielposition gelegt.

Um ein Element zu transformieren und aus dem Elementfluss zu entfernen, können Sie zusätzlich die Eigenschaft position auf absolute oder fixed setzen. Der Browser platziert das Element zunächst gemäß der position-Eigenschaft und transformiert es dann.

Eine Verschiebung alleine zeigt ihren Nutzen erst in Kombination mit anderen Transformationen:

scale

Die scale-Eigenschaft streckt, staucht oder verzerrt die Form eines HTML- oder SVG-Elements.

Sie erwartet einen, zwei oder drei Zahlenwerte als Streckungsfaktor(en).

Der Streckungsfaktor ist eine Zahl, das „Streckungszentrum“ (mathematisch korrekt die Fixpunktgerade) wird durch die Eigenschaft transform-origin festgelegt. Wird dazu keine Angabe gemacht, so ist die Fixpunktgerade die durch den Mittelpunkt des Elements verlaufende Vertikale. Streckungsfaktoren größer als Eins vergrößern (strecken) das Element, Faktoren zwischen Null und Eins stauchen es und negative Faktoren spiegeln das Element an der Fixpunktgeraden.

Der Vollständigkeit halber sei erwähnt, dass k = 1 das Element unverändert lässt, wohingegen k = 0 die Breite des Elements auf Null setzt.

So können Sie eine Parallelstreckung entlang der Horizontalen erreichen. Mit einem negativen Streckungsfaktor können Sie einzelne Wörter oder Buchstaben spiegeln:

Spiegelung eines Texts ansehen …
.gespiegelt {
	color: #c82f04;
	display: inline-block;
	scale: -1 1;
}

Alle Elemente der Klasse .gespiegelt werden entlang der x-Achse gespiegelt. Damit dies bei den inline-Elementen span funktioniert, müssen sie einen display:inline-block bekommen.

scale: -1 1 benötigt einen zweiten Parameter, damit nur die X-Achse gespigelt wird; hier wäre transform: scaleX(-1) übersichtlicher.

Stauchung eines SVG-Objekts mit scale ansehen …
#scale1:hover {
	scale: 2 0.5;
	translate: -50px 25px;
}

#scale2:hover {
	scale: 2 0.5;
}

Innerhalb des svg-Elements werden zwei Sterne mit einem path-Element gezeichnet.

Hovert die Maus über einen Stern, wird dieser in der X-Achse um das Zweifache gestreckt und in der y-Achse auf die Hälfte gestaucht. Damit das Objekt nicht aus dem Element wandert, erfolgt beim linken Stern zusätzlich eine Verschiebung mit translate.


Beachten Sie: Die „neuen“ CSS-Eigenschaften folgen der gewohnten CSS-Syntax:
  • scale erfordert ein, zwei oder drei mit Leerzeichen getrennte Zahlenwerte ohne umschließende Klammern.
  • die gleichlautende scale()-Funktion erfordert dagegen zwei kommaseparierte Werte innerhalb der Klammer.

rotate

Die rotate-Eigenschaft dreht die Form eines HTML oder SVG-Elements. Sie wurde im CSS Transforms Module Level 2 als zusätzliche Möglichkeit bereitgestellt, ein Element unabhängig von den übrigen Transformationen rotieren zu können.

Kombination einer Drehung und Skalierung ansehen …
@keyframes pulse {
	from {
		scale: 1;
	}
	to {
		scale: 1.2;
	}
}

svg {
	fill: rebeccapurple;
	rotate: .40turn;
	animation: 1s infinite alternate pulse;
}

Der Pfeil erhält zwei Transformationen. Die Animation der scale-Eigenschaft läuft unabhängig von der Drehung durch rotate ab.

Beachten Sie, dass die beiden Eigenschaften normale Werte erfordern, die anders als in Funktionen ohne umschließende Klammer notiert werden.

Siehe auch Drehen, Kreisen und Pendeln

transform-Eigenschaft

Die klassische Eigenschaft für Transformationen ist die transform-Eigenschaft. Sie wendet eine 2D- oder 3D-Transformation auf ein Element an, indem eine oder mehrere Transform-Funktionen angewandt werden.

Die Syntax entspricht der „normalen“ CSS-Schreibweise:

transform: … function3(…) function2(…) function1(…);  

Diese Transform-Funktionen gibt es:

Kombination zweier transform-Funktionen ansehen …
#scale1:hover {
	transform: translate(-50px) scale(2, 0.5);
}

#scale2:hover {
	transform: scale(2, 0.5) translate(-50px, 25px);
}

Das Beispiel scheint identisch zum oberen Beispiel. Allerdings wird hier die transform-Eigenschaft verwendet. Nach dem Namen der Eigenschaft folgen mehrere durch Leerzeichen separierte CSS-Funktionen:

  • die translate()-Funktion führt die Verschiebung eines Elements aus. Sie benötigt folgende Parameter:
    • eine (positive oder negative) Längenangabe für die horizontale Verschiebung,
    • eine (optionale) Längenangabe für die vertikale Verschiebung
      Wenn nur ein Wert angegeben wird, wird nur die x-Achse verschoben.
  • die scale()-Funktion für eine Streckung. Sie benötigt folgende Parameter:
    • ein (positiver oder negativer) Zahlenwert für die horizontale
    • eine (optionaler) Zahlenwert für die vertikale Streckung
      Wird nur eine Zahl angegeben, so gilt dieser Streckungsfaktor für beide Richtungen.
Beachten Sie:
Im Unterschied zur CSS-Syntax für Eigenschaften werden die Parameter in den CSS-Funktionen durch Kommas separiert!

Die Funktionen werden von rechts nach links abgearbeitet:

  • der linke Stern wird gestreckt und dann, da auch der Startpunkt des path-Elements skaliert wird, wieder an seinen Ausgangspunkt verschoben.
  • der linke Stern wird zuerst verschoben und dann gestreckt. Nach der Transformation findet er sich an anderer Stelle wieder.

Ausführungsreihenfolge mehrerer Transformationen

Gerade wenn Skalierungen oder Rotationen im Spiel sind, ist die Reihenfolge, in der Transformationen angewendet werden, von Bedeutung. Das ist schon kompliziert genug, wenn nur die transform-Eigenschaft genutzt wird, und zusammen mit den übrigen Eigenschaften, die ein Element verschieben können, wird es nicht einfacher.

Eine Einführung dazu, wie der Browser mehrere Transformationen zu einer 3D-Matrix kombiniert, finden Sie bei der Beschreibung von matrix3D()). Die CSS Spezifikation[2] definiert eindeutig, in welcher Reihenfolge diese Kombination vorzunehmen ist, und dadurch entsteht die folgende Ausführungsreihenfolge:

  1. Verschiebe das Element um den negierten transform-origin Vektor. Das geschieht, weil die Berechnungen, die einen Punkt um einen bestimmten Winkel drehen können, immer auf den Nullpunkt des Koordinatensystems bezogen sind. Diese erste Verschiebung bringt den gewünschten Bezugspunkt der Transformation nach (0,0,0).
  2. Wende die Transform-Funktionen der transform-Eigenschaft von rechts nach links an. Die zuletzt notierte Transform-Funktion wird zuerst ausgeführt - das vergisst man gerne
  3. Wende die offset-Eigenschaft an
  4. Wende die scale-Eigenschaft an
  5. Wende die rotate-Eigenschaft an
  6. Wende die translate-Eigenschaft an
  7. Verschiebe das Element um den transform-origin-Vektor, d.h. Schritt 1 wird rückgängig gemacht.

Neigen und Verzerren mit skewX()

Mit skewX() können Sie ein Element neigen, bzw. verzerren. Durch dieses Schrägstellen können Sie rechteckige Elemente zu Parallelogrammen neigen. Im folgenden Beispiel sollen die Listenelemente der Navigation pfeilartig angeschrägt werden.

angeschrägtes Menü aus Parallelogrammen ansehen …
ul a {
    background: lightgrey;
    border: thin solid grey;
    display: block;
    margin: 0.5em 1em;
    padding: 0.5em 1em;
    text-decoration: none;
    transform: skewX(-30deg);
}

ul a:hover {
    background: #dfac20;
}

Die Elemente der Navigation werden zu Parallelogrammen verzerrt – leider aber auch der Text der beinhalteten Links!

Eine Möglichkeit wäre es, einem Kind-Element ul li a span eine entsprechende positive Verzerrung zu geben. Allerdings würde der Text dann zweimal verzerrt werden und entsprechend unscharf dargestellt.

In der hier verwendeten Alternative werden die angeschrägten Parallelogramme nun durch Pseudoelemente ul a::before gebildet. Diese werden mit z-index:-1; in den Hintergrund geschoben.

Die Links der Navigation werden normal darüber dargestellt.

angeschrägtes Menü aus Parallelogrammen-2 ansehen …
ul a {
  display: block;
  margin: 0.5em 1em;
  position: relative;
  text-decoration: none;
  z-index: 0;
}

ul a::before {
  background: lightgrey;
  border: thin solid grey;
  content: "\A0 ";
  display: block;
  height: 100%;
  margin: -0.5em -1em;
  padding: 0.5em 1em;
  position: absolute;
  transform: skewX(-30deg);
  width: 100%;
  z-index: -1;
}
Beachten Sie: ⚠️Die Funktion skew() ist nicht in den letzten Entwurf des w3c.org übernommen worden. MDN empfiehlt stattdessen bei einem Parameter skewX() und bei mehreren Parametern matrix() zu verwenden. Sowohl skewX() und skewY() wirken nur auf transformable elements – das sind im Wesentlichen Blockelemente und solche, die durch CSS zu Block-Level-Elementen gemacht wurden.

Transformationen kombinieren

ul a::before {
  transform: skewX(-30%);
}
ul a:hover::before {
  /* überschreibt (wsl. unbeabsichtigt) die vorherige Tranfromation mit skewX() */
  transform: scale(1.2);
}

Eigentlich ist dieses CSS nicht falsch - es arbeitet nur anders als beabsichtigt. Anstatt die beiden CSS-Funktionen zu kombinieren, überschreibt die zweite Zuweisung den ersten Regelsatz.[3]

Die funktionierende Lösung wäre es, alle Funktionen in den Regelsatz einzuschließen, was aber dem WET-Grundsatz widerspricht.

ul a::before {
	transform: skewX(-30deg);
}

ul a:hover::before {
	transform: translate(-5px) scale(1.1) skewX(-30deg);
}

Alternativ könnte man die kombinierte Transformation nur einmal notieren und die Werte mit custom properties immer wieder neu setzen:

ul a::before {
	transform: translate(var(--translate)) scale(var(--scale)) skewX(-30deg);
	--scale: 1;
	--translate: 0;
}

ul a:hover::before {
	--scale: 1.2;
	--translate: -10px;
}

kombinierte Transformationen animieren

Wenn Sie die Transform-Eigenschaft animieren möchten, dann müssen Sie wissen, wie der Browser dabei vorgeht. Es sind nämlich mehrere Fälle zu unterscheiden:

Alle Transform-Funktionen von Start- und Zielzustand sind gleich
In diesem Fall animiert der Browser jede Transform-Funktion einzeln. „Überrotationen“ wie (rotate(720deg) bleiben dabei erhalten.
Ein Endzustand ist eine Erweiterung des anderen Endzustandes
Dieser Fall liegt zum Beispiel vor, wenn an den Startzustand weitere Transform-Funktionen hinten angefügt werden. Der Browser sucht sich nun zu jeder angefügten Funktion den Wert, der zu einer identischen Transformation führt, also translate(0,0) oder scale(1), erweitert den kürzeren Zustand damit und animiert dann wieder jede Transform-Funktion einzeln
Die 1:1 Zuordnung der Transform-Funktionen zwischen Start- und Endzustand kann nicht hergestellt werden
Der Browser bildet von links nach rechts eine möglichst lange Kette zueinander passender Funktionen. Die übrigen Transform-Funktionen fasst er im Start- und Endzustanden jeweils zu einer Transformationsmatrix zusammen und interpoliert dann diese Matrix. Das geschieht nicht stumpf durch Interpolation der Matrix-Einzelwerte, statt dessen führt er eine Dekomposition der Matrizen in Einzeltransformationen durch, wodurch eine Liste von Transformationsfunktionen entsteht, deren Reihenfolge immer gleich ist. Und diese Einzeltransformationen werden dann interpoliert.

Sobald Sie den Browser zu einer Matrix-Animation zwingen, müssen Sie auf Überrotationen verzichten. Der Rotationswinkel wird in Form von Sinus- und Cosinuswerten in die Matrix eingearbeitet, wodurch Winkel auf das Intervall [0°, 360°[ normiert werden.

Ein weiteres Problem bei animierten Transformationen ist, dass Sie für Anfangs- und Endzustand immer die vollständige Liste der zu verwendenden Funktionen aufschreiben müssen. Das führt bei späteren Änderungen schnell zu Fehlern, oder zumindest zu viel Arbeit, wenn eine Animation geändert werden soll und mehrere Keyframes vorliegen.

Wenn Sie das nicht möchten, gibt es mehrere Lösungsansätze.

Zum einen können Sie prüfen, ob die neuen Einzeleigenschaften translate, scale und rotate für Ihren Zweck passend sind. Schauen Sie sich dazu die Ausführungsreihenfolge der Transformationen an. Diese Eigenschaften können Sie unabhängig von der transform-Eigenschaft animieren.

Alternative mit custom properties

Das umständliche Notieren aller Transformations-Funktionen lässt sich auch mithilfe von registrierten custom properties vereinfachen. Während unregistrierte custom properties vom Browser als Zeichenketten behandelt werden, die sich nur als "ist da" oder "ist nicht da" animieren lassen, kann die Registrierung dem Browser einen numerischen Datentyp für das Property liefern, für den eine Interpolation möglich ist.

Voraussetzung für diese Methode ist, dass die verwendeten Transform-Funktionen während der Animation gleich bleiben. Dann können Sie die Transformationsfunktion in dem HTML Element, das Sie animieren möchten, notieren und die Werte darin, die animiert werden sollen, durch custom properties angeben:

transform: rotate(.45turn) scale(var(--scale, 1));

Wenn Sie das custom property --scale nun als Zahl deklarieren, können Sie es in der @keyframes-Regel animieren und der Browser passt die Transformation entsprechend an. Von der zusätzlichen Rotation brauchen Ihre Keyframes dann nichts mehr zu wissen. Allerdings ist die Registrierung von custom properties derzeit (2022) nur in Browsern der Chrome-Familie einsetzbar. Firefox und Safari unterstützen dagegen die Einzeleigenschaften, bei denen Chrome wiederum erst im August 2022 nachgezogen ist. Diese Methode ist deshalb zur Zeit nur für Anwendungsfälle relevant, wo Sie mit Einzeleigenschaften nicht zurechtkommen und wo Sie außerhalb der Chrome-Welt auch auf die Animation verzichten können.

Das folgende Beispiel verwendet in älteren Chrome-Browsern custom properties und in Browsern, die die rotate-Eigenschaft unterstützen, Einzeleigenschaften.

Werte mit custom properties setzen ansehen …
@property --scale {
   syntax: "<number>";
   inherits: true;
   initial-value: 1;
}

@keyframes pulse {
	from { --scale: 1.0; }
	to   { --scale: 1.2; }
}

svg {
	fill: rebeccapurple;
	width: 12em;
	transform: rotate(.45turn) scale(var(--scale, 1));
	animation: 1s infinite alternate custom-pulse;
}

@supports (rotate: .45turn) {
	svg {
		transform: none;
		rotate: .45turn;
	}
	@keyframes pulse {
		from { scale: 1.0; }
		to   { scale: 1.2; }
	}
}

@property legt fest, dass die selbstdefinierte Eigenschaft --scale nur einheitenlose Zahlen enthalten darf, vererbt werden kann und einen Standardwert von 1 hat.

Die Feature-Abfrage auf rotate: .45turn bewirkt, dass aktuelle Browser durchweg die Animation mit Einzeleigenschaften verwenden. Etwas ältere Chromebrowser fallen auf die custom property Animation zurück. Und Browser, die beides nicht kennen, lassen die Pfeilgröße zwischen klein und groß springen.

Siehe auch

  • Polaroid-Bildergalerie
    In dieser Bildergalerie werden Bilder als kleinere Vorschauansichten angezeigt. Ein Berühren mit der Maus skaliert sie auf die Originalgröße. Zusätzlich erscheint die bisher durch verborgene figcaption als Bildunterschrift.
  • SVG/Tutorials/Rube-Goldberg-Maschinen
    unnötig komplizierte Maschinen, bei denen eine eigentlich triviale Aktion durch eine Kette nacheinander ablaufender Aktionen ausgelöst wird. Die SVG-Elemente werden mit CSS-Transforms animiert.
  • SELFHTML-Forum: Erläuterung der Orientierung der Scherung von Gunnar Bittersmann

Weblinks

  1. CSSWG: CSS Transforms Module Level 2
  2. CSS Transforms 2
  3. css-tricks: Individual CSS Transform Functions Chris Coyier on Feb 23, 2017