mitmario.dev

transition

CSS Im Browser 5 Min Lesezeit 3 BeispieleLektion 1 von 6

Du fährst mit der Maus über einen Button, und er wird dunkler. Ohne weiteres Zutun passiert das in einem einzigen Bild, eben noch hell und jetzt dunkel. Nicht falsch, nur hart. transition legt eine Strecke zwischen die beiden Zustände, und die Bilder dazwischen rechnet der Browser aus.

Der Übergang gehört an den Ruhezustand

Der Übergang steht am Ruhezustand
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 24px;
  font-family: system-ui, sans-serif;
  line-height: 1.5;
}

.button {
  min-height: 44px;
  padding: 8px 16px;
  border: 0;
  border-radius: 8px;
  font: inherit;
  color: #ffffff;
  background-color: #2563eb;
  cursor: pointer;

  /* Diese drei Zeilen stehen am Ruhezustand und gelten
     deshalb für das Hinfahren und für das Verlassen. */
  transition-property: background-color;
  transition-duration: 0.2s;
  transition-timing-function: ease-out;
}

.button:hover {
  background-color: #1d4ed8;
}

.hinweis {
  max-width: 60ch;
  color: #52525b;
}

Hier steht der Übergang an der Grundregel des Elements und nicht an :hover.

Das hat einen einfachen Grund. Eine Regel gilt nur, solange ihre Bedingung erfüllt ist. Steht der Übergang in .button:hover, dann gibt es ihn nur, solange der Zeiger auf dem Button liegt. Sobald der Zeiger weggeht, ist die Regel weg und der Übergang mit ihr. Für den Rückweg bleibt nichts übrig, was ihn weich machen könnte.

Derselbe Übergang am Hover
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 24px;
  font-family: system-ui, sans-serif;
  line-height: 1.5;
}

.button {
  min-height: 44px;
  padding: 8px 16px;
  border: 0;
  border-radius: 8px;
  font: inherit;
  color: #ffffff;
  background-color: #2563eb;
  cursor: pointer;
}

.button:hover {
  background-color: #1d4ed8;

  /* Hier ist der Übergang falsch aufgehoben. */
  transition: background-color 0.2s ease-out;
}

.hinweis {
  max-width: 60ch;
  color: #52525b;
}

Im ersten Beispiel geht beides weich, hin und wieder weg. Im zweiten schnappt die Farbe beim Verlassen zurück. Wenn es weich hingeht und hart zurück, steht der Übergang an der falschen Stelle.

Was davon im Stylesheet ankommt, siehst du im Auskunftsstreifen des Inspectors. Beim Button im ersten Beispiel steht ganz unten transition: background-color 0.2s ease-out, zusammengesetzt aus den drei Zeilen im Stylesheet. Alles zur Bewegung steht dort am Ende der Liste. Ist der Streifen zu niedrig, ziehst du ihn an seiner Oberkante größer. Der Zeiger liegt dabei ja auf dem Button, also läuft der Übergang gerade. Du kannst zusehen, wie die Zeile background-color von rgb(37, 99, 235) nach rgb(29, 78, 216) wandert, und das dauert genau die 0,2 Sekunden, die daneben stehen.

Im zweiten Beispiel steht auf dem Button dieselbe Zeile, denn dort gilt gerade die Hover-Regel. Der Unterschied kommt erst beim Weggehen. Auch den bekommst du in den Streifen, wenn du den Button vorher festklickst. Ein Klick friert die Auswahl ein, und gemessen wird weiter, auch wenn der Zeiger längst woanders ist. Im ersten Beispiel bleibt die transition-Zeile dann stehen, und background-color läuft in ein paar Schritten zurück auf rgb(37, 99, 235). Im zweiten ist die Zeile weg, und die Farbe steht sofort wieder dort.

Die vier Eigenschaften

transition-property nennt, was überhaupt weich werden soll. Mehrere Eigenschaften trennst du mit Komma. In transition-duration steht, wie lange es dauert, in Sekunden oder Millisekunden. transition-timing-function verteilt das Tempo über die Strecke. Und transition-delay wartet, bevor es losgeht.

Mit dem Shorthand transition: background-color 0.2s ease-out; steht dasselbe in einer Zeile. Die Reihenfolge ist frei, bis auf eine Regel. Bei zwei Zeitangaben ist die erste die Dauer und die zweite die Verzögerung.

Mehrere Eigenschaften stehen mit Komma hintereinander, jede mit ihren eigenen Werten, etwa transition: color 0.15s, box-shadow 0.3s ease-out;.

Wie lang, und mit welcher Kurve

Bei kleinen Wechseln wie Farbe, Rahmen oder Schatten liegst du mit 150 bis 250 Millisekunden richtig. Alles über 400 fühlt sich träge an, denn dann läuft die Oberfläche der Hand hinterher und nicht umgekehrt. Größere Bewegungen über den halben Bildschirm dürfen 300 bis 400 brauchen. Mehr fast nie.

Vier Kurven im Vergleich
*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 24px;
  font-family: system-ui, sans-serif;
  line-height: 1.5;
}

.bahnen {
  padding: 16px;
  border-radius: 12px;
  background-color: #f4f4f5;
}

.bahn {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 8px 0;
  font-size: 14px;
  color: #52525b;
}

.balken {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  background-color: #2563eb;
  transition-property: width;
  transition-duration: 1.2s;
}

.linear {
  transition-timing-function: linear;
}

.ein {
  transition-timing-function: ease-in;
}

.aus {
  transition-timing-function: ease-out;
}

.beides {
  transition-timing-function: ease-in-out;
}

.bahnen:hover .balken {
  width: 200px;
}

.hinweis {
  max-width: 60ch;
  color: #52525b;
}

Die vier Balken starten gleichzeitig und sind gleichzeitig fertig. Was dazwischen passiert, kannst du mitlesen. Bei jedem Balken steht im Streifen seine Kurve (transition: width 1.2s ease-in) und darüber die width, die gerade gilt.

Ein Element, das sich bewegt, verliert man leicht mit dem Zeiger. Wenn du es festklickst wie eben den Button, bleibt es im Streifen. Das hilft im ganzen Abschnitt, denn sonst rutscht dir ein hüpfender Punkt unter der Maus weg und im Streifen steht plötzlich sein Elternteil statt des Elements, das du eigentlich sehen wolltest.

Misst man alle 150 Millisekunden, sieht der Unterschied so aus. linear legt jedes Mal 23 Pixel zu, und die Breite geht von 16 über 39, 62 und 85 bis 200. ease-in fängt mit 5 Pixeln an und hört mit 37 auf (21 · 33 · 51 … 130 · 163 · 200). Bei ease-out ist es genau umgekehrt. Der erste Schritt ist 37 Pixel groß und der letzte nur noch 5 (53 · 86 · 115 … 183 · 195 · 200).

Die Kurve entscheidet also, wo innerhalb dieser Zeit das Tempo liegt:

  • ease-out startet schnell und bremst weich ab. Das ist die Kurve für alles, was erscheint oder ankommt, und die häufigste überhaupt.
  • ease-in startet langsam und wird schneller. Passt für alles, was verschwindet.
  • ease-in-out macht beides und wirkt bei längeren Wegen am natürlichsten.
  • linear hält das Tempo. Bei etwas, das sich über den Bildschirm bewegt, sieht das mechanisch aus. Richtig ist es trotzdem oft: bei einer Endlosdrehung, die keinen Anfang und kein Ende hat, bei einem Fortschrittsbalken, und bei Farbe oder Deckkraft sieht man den Unterschied zu einer Kurve ohnehin kaum.

Reichen dir die vier nicht, baust du mit cubic-bezier() eine eigene Kurve. steps() macht aus der weichen Bewegung eine, die in Stufen ruckelt.

Zwei Stolpersteine

transition: all ist bequem und teuer. Der Browser beobachtet dann bei jeder Änderung jede animierbare Eigenschaft, auch die hundert, die sich nie ändern. Außerdem erwischt es Dinge, die gar nicht animiert werden sollten, und später sucht man dann, warum ein Element beim Laden komisch zuckt. Ich schreibe deshalb hin, was ich meine.

Nicht alles lässt sich animieren. Der Browser braucht zwei Zahlen, zwischen denen er rechnen kann. Von display: none nach display: block gibt es keine Zwischenwerte. Und height: auto ist gar keine Zahl, also rechnet er zwischen ihr und 0px von allein nichts aus. Das sind die beiden klassischen Enttäuschungen. Den Ausweg für height: auto gibt es in Lektion 13.5, den für display in 15.7.

In der Aufgabe reagieren eine Karte und ein Button schon auf den Zeiger, bisher aber ohne jeden Übergang.

Zum Mitnehmen

Ein Übergang steht am Ruhezustand, nicht an :hover, sonst springt der Rückweg. Er nennt die Eigenschaften, die sich ändern, statt all, und für kleine Wechsel reichen 150 bis 250 Millisekunden.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe im Editor, direkt im Browser geprüft

    Öffnet sich mit dem Basis Konto.