CSS3: transition (Übergänge für sanfte Animationen)

Dank CSS3 ist es nun auch möglich, Webseiten ohne Flash, animierte GIFs oder JavaScript zu animieren. So ist der Genuss von Effekten ohne Plugin oder unzählige HTTP-Requests möglich, während der Einbau dennoch ohne komplexe Script-Konstruktionen möglich ist. Wenn diese Möglichkeiten geschickt genutzt werden, dann können sie einen wirklichen Mehrwert für das WWW darstellen. Hoffentlich wird durch sie aber nicht eine neue Generation Beepworld-Seiten (Achtung, Ironie!) geboren. Daher sollte nur derjenige weiterlesen, der seriöse gestalterische Ziele verfolgt. 😉

In diesem Beitrag geht es um das Transitions-Modul, welches fälschlicherweise oft mit dem Animations-Modul gleichgesetzt wird. Während eine Animation normalerweise direkt auf der geladenen Seite startet und eine Folge von Keyframes abarbeitet, ggf. beeinflusst von Interaktionen des Users, bis letztlich ein Endzustand erreicht wurde, überführt eine Transition (engl. für Übergang) ein Objekt nach Auslösung eines Triggers (z.B. die Pseudoklasse :hover) von einem per CSS beschriebenen Zustand in einen anderen Zustand und wieder zurück, sobald der Trigger nicht mehr ausgelöst ist.

Das klingt erstmal komplizierter als es ist. An diesem Punkt ist wichtig: Während die Animationen für eher komplexere Aufgaben gedacht sind, zeigen die Transitions ihre Stärke beispielsweise bei Hover-Effekten. Unterstützt werden Transitions bereits von allen modernen Browsern außer dem Internet Explorer, der wohl erst mit Version 10 nachzieht.

Definition

Zunächst empfiehlt sich ein Blick auf die Definition der einzelnen Eigenschaften des Transition-Moduls. Den Anfang macht die Eigenschaft transition-property:

<transition-property> = [none|[all|<Eigenschaft>][‘,’[all|<Eigenschaft>]]*]

Der einfachste Fall ist schnell erklärt: Ist der Wert none, ist keine CSS-Eigenschaft von der Transition betroffen. Ansonsten folgt eine Aufzählung von CSS-Eigenschaften oder das Schlüsselwort all (für alle möglichen CSS-Eigenschaften), die betroffen sein sollen. Die Vermischung von all mit Eigenschaften macht dabei durchaus Sinn: Über die Eigenschaften des Transition-Moduls, die gleich erläutert werden, können Parameter des Übergangs einzeln gesteuert werden. Default-Wert ist all.

Die nächste interessante Eigenschaft nennt sich transition-duration:

<transition-duration> = [<time>[,<time>]*]

Diese Eigenschaft definiert, wie lange der Übergang einer einzelnen Eigenschaft dauern darf, z.B. 2s für 2 Sekunden. Ein einzelner Wert würde sich dabei auf alle bei transition-property aufgezählten Eigenschaften auswirken. Alternativ können auch mehrere unterschiedliche Werte angegeben werden, die dann “Reih-um” den Eigenschaften zugeordnet werden.

Eine ähnliche Eigenschaft ist transition-delay:

<transition-delay> = [<time>[,<time>]*]

Sie legt jedoch nicht fest, wie lange eine Transition andauern soll, sondern mit welcher zeitlichen Verzögerung sie starten soll.

Besonders interessant ist aber noch die transition-timing-function:

<transition-timing-function> =
[
  [ease|linear|ease-in|ease-out|ease-in-out|step-start|step-end|steps(<integer>[,[start|end]]?)
  |cubic-bezier(<number>,<number>,<number>,<number>)]
  [
    ,[ease|linear|ease-in|ease-out|ease-in-out|step-start|step-end|steps(<number>[,[start|end]]?)
    |cubic-bezier(<number>,<number>,<number>,<number>)]
  ]*
]

Diese Eigenschaft sieht auf den ersten Blick deutlich schlimmer aus, als sie eigentlich ist. Sie dient dazu, die Geschwindigkeit der Transition über die festgelegte Zeit (duration) festzulegen. Beispielsweise ist es möglich, dass die Veränderung langsam beginnt, schneller wird und zum Ende hin wieder langsamer, oder dass die Veränderung in “harten” Schritten erfolgt. Um dies zu Beschreiben, kann entweder eine kubische Bézierkurve beschrieben, eine Schrittzahl angegeben oder ein definiertes Alias angegeben werden. Wie zuvor können mehrere durch Komma getrennte Angaben gemacht werden, die “Reih-um” auf die Eigenschaften bezogen werden.

Im Einzelnen sieht das wie folgt aus:

Kubische Bézierkurve (animiert)cubic-bezier(<x1>,<y1>,<x2>,<y2>): Eine kubische Bézierkurve ist immer durch 4 Punkte definiert. Zwei Punkte, P0(0|0) und P3(1|1), stehen fest, die anderen beiden, P1(x1|y1) und P2(x2|y2), werden durch diesen Aufruf mit Werten zwischen 0 und 1 festgelegt. Um mehr über Bézierkurven zu erfahren, empfehle ich den verlinkten Wikipedia-Artikel. Von dort stammt auch die nebenstehende, gemeinfreie Animation, die das Prinzip schön visualisiert.

steps(<integer>[,[start|end]]?): Alternativ können einzelne Schritte definiert werden. Dabei gibt die Integer-Zahl an, in wievielen Schritten die Transition erfolgen soll. Eine 4 Sekunden lange Veränderung mit 4 Schritten ergibt also eine sprunghafte Änderung in jeder Sekunde. Mit einem zweiten Wert start definiert man zudem den Startzeitpunkt als ersten Schritt, mit der Angabe end definiert man den Endzeitpunkt als letzten Schritt. In unserem 4-Sekunden-Beispiel würden die Veränderungen bei start nach 0, 1, 2 und 3 Sekunden vorgenommen, bei end hingegen nach 1, 2, 3 und 4 Sekunden. Wird kein zweiter Wert angenommen, so gilt als Default-Wert end.

Ansonsten kann man sich ein Alias aus der folgenden Liste auswählen, um sich die genaue Definition des Ablaufs zu sparen:

  • ease: Entspricht cubic-bezier(0.25, 0.1, 0.25, 1.0), ist der Default-Wert.
  • linear: Entspricht cubic-bezier(0.0, 0.0, 1.0, 1.0).
  • ease-in: Entspricht cubic-bezier(0.42, 0, 1.0, 1.0).
  • ease-out: Entspricht cubic-bezier(0, 0, 0.58, 1.0).
  • ease-in-out: Entspricht cubic-bezier(0.42, 0, 0.58, 1.0).
  • step-start: Entspricht steps(1, start).
  • step-end: Entspricht steps(1, end).

Als letzte Eigenschaft des Transition-Moduls ist noch transition selbst zu nennen. Diese Eigenschaft erlaubt durch folgende Syntax alle bisherigen Eigenschaften zusammenzufassen:

<transition> = [<transition-property> || <transition-duration> || <transition-timing-function> || <transition-delay> [, [<transition-property> || <transition-duration> || <transition-timing-function> || <transition-delay>]]*

Solange sich die Eigenschaft noch in Entwicklung befindet, verwenden Opera-, Webkit- und Mozilla-Browser ein Präfix. Möchte man sie bereits verwenden, muss sie daher mehrfach mit gleichen Parametern definiert werden: transition (Standard), -moz-transition (Mozilla), -webkit-transition (Safari und Chrome), -o-transitio (Opera).

Beispiele

Doch jetzt genug trockene Theorie. Beispiele sagen immer mehr als viele Worte. Daher zunächst ein einfaches Beispiel zur Verbindung aus transition-troperty und transition-duration:


div.demobox {
width:50px; background:#000; /* Start*/
transition-property: width, background;
transition-duration: 4s, 1s;
}
div.demobox:hover {
width:200px; background:#eee; /* Ziel */
}

Um den Effekt zu sehen, muss man einfach mit der Maus über das schwarze Kästchen fahren:

Live-Demo
Testbox

Der Farbwechsel ist schneller (nach 1 Sekunde) abgeschlossen, als die Änderung der Länge (4 Sekunden).

Via transition-delay können die Effekte auch nacheinander ausgeführt werden:


div.demobox {
width:50px; background:#000; /* Start*/
transition-property: width, background;
transition-duration: 2s, 2s;
transition-delay: 0s, 2s;
}
div.demobox:hover {
width:200px; background:#eee; /* Ziel */
}

Hier ist jetzt zu sehen, dass sich erst die Länge ändert, und anschließend die Farbe wechselt:

Live-Demo
Testbox

Die bisherigen Beispiele liefen alle mit der Vorgabe ease als transition-timing-function. Im Gegensatz dazu jetzt einmal linear, auch eine vorgegebene cubic-bezier:


div.demobox {
width:50px; background:#000; /* Start*/
transition-duration: 4s;
transition-timing-function: linear;
}
div.demobox:hover {
width:200px; background:#eee; /* Ziel */
}

Der obere Kasten ist mit linear, der untere zum Vergleich nochmal mit ease versehen – beide Varianten laufen insgesamt 4 Sekunden:

Live-Demo
Testbox

 

Testbox

Abschließend nun noch ein Beispiel mit steps als Alternative:


div.demobox {
width:50px; background:#000; /* Start*/
transition-duration: 4s;
transition-timing-function: steps(4,start);
}
div.demobox:hover {
width:200px; background:#eee; /* Ziel */
}

Der obere Kasten ist mit start als 2. Parameter (wie oben gezeigt), der untere zum Vergleich mit end versehen, beide machen 4 Schritte in 4 Sekunden:

Live-Demo
Testbox

 

Testbox