Abschnitt 13 · Lektion 1
transition
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
<button class="button">Absenden</button>
<p class="hinweis">
Fahr mit der Maus darüber und wieder weg. Beide Richtungen
laufen weich, denn der Übergang gehört dem Button und nicht
dem Überfahren.
</p> *,
*::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.
<button class="button">Absenden</button>
<p class="hinweis">
Fahr darüber und wieder weg. Das Hinfahren ist weich, das
Verlassen springt. Sobald der Zeiger weg ist, gilt die
Hover-Regel nicht mehr, und mit ihr verschwindet der
Übergang.
</p> *,
*::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.
<div class="bahnen">
<p class="bahn"><span class="balken linear"></span>linear</p>
<p class="bahn"><span class="balken ein"></span>ease-in</p>
<p class="bahn"><span class="balken aus"></span>ease-out</p>
<p class="bahn"><span class="balken beides"></span>ease-in-out</p>
</div>
<p class="hinweis">
Fahr über den Kasten. Alle vier starten gleichzeitig und
sind gleichzeitig fertig. Verschieden ist nur, wann sie
unterwegs schnell sind.
</p> *,
*::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-outstartet schnell und bremst weich ab. Das ist die Kurve für alles, was erscheint oder ankommt, und die häufigste überhaupt.ease-instartet langsam und wird schneller. Passt für alles, was verschwindet.ease-in-outmacht beides und wirkt bei längeren Wegen am natürlichsten.linearhä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, kostenlosZu 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.