Scroll-gesteuerte Animationen
Ein häufiges UI-Muster beinhaltet Elemente, die sich animieren, während der Benutzer vertikal oder horizontal über eine Seite scrollt. Diese scroll-gesteuerten Animationen treten als direkte Reaktion auf das Scrollen der Seite oder einen überlaufenden Scroll-Container innerhalb einer Seite auf.
Die im Modul CSS scroll-gesteuerte Animationen definierten Eigenschaften erweitern CSS-Animationen, indem sie ermöglichen, die Werte von animierenden Eigenschaften zu definieren, die in @keyframes-Animationen als Reaktion auf Benutzereingriffe verwendet werden.
Dieser Leitfaden bietet einen Überblick über die Verwendung von CSS zur Erstellung von scroll-gesteuerten Animations-Timelines und Animationen.
Was sind scroll-gesteuerte Animationen?
Das Modul CSS scroll-gesteuerte Animationen definiert Eigenschaften, die es ermöglichen, CSS-Keyframe-Animationen mit dem Scrollen zu verknüpfen.
Fortschritt der Timeline
Animationen können so eingestellt werden, dass sie entlang einer scroll-basierten Timeline voranschreiten, anstatt entlang der standardmäßigen zeitbasierten Dokumenten-Timeline, ohne dass JavaScript erforderlich ist. Mit CSS können wir definieren, welche Animations-Timeline verwendet werden soll, einschließlich des Animierens von Elementen durch das Scrollen eines scrollbaren Elements, anstatt durch den Zeitverlauf.
Leistungsverbesserungen
CSS scroll-gesteuerte Animationen sind performant. JavaScript scroll-gesteuerte Animationen erfordern scroll-Ereignis-Listener und IntersectionObserver-Objekte im Haupt-Thread, um Elemente über den Scrollport hinweg zu verfolgen. Jedes Mal, wenn Sie sich auf den Haupt-Thread verlassen, um Effekte mit JavaScript zu rendern, besteht die Gefahr, den Haupt-Thread zu blockieren, was zu einer unansprechbaren Seite und einer schlechten Benutzererfahrung oder Rucklern führen kann.
Grundlagen
Scroll-gesteuerte Animationen bauen auf CSS-Animationen und der Web Animations API auf. Bevor Sie scroll-gesteuerte Animationen erstellen, müssen Sie ein Verständnis von CSS-@keyframes-Animationen haben. Weitere Informationen finden Sie im Leitfaden zur Verwendung von CSS-Animationen.
In CSS werden Animationen erstellt, indem Keyframe-Animationen unter Verwendung der animation-name-Eigenschaft (oder der animation-Kurzform) einem Element zugeordnet werden. Standardmäßig laufen Animationen auf der standardmäßigen Dokumenten-Timeline, wobei sie sich von der from-Keyframe zur to-Keyframe bewegen, während die Zeit vergeht, und die Animation so lange andauert, wie es durch den Wert der animation-duration-Eigenschaft definiert ist. Wenn sie auf der standardmäßigen Dokumenten-Timeline laufen, werden Animationen bis zum Ende abgespielt, es sei denn, sie werden daran gehindert, zum Beispiel durch das Setzen des animation-play-state auf paused oder durch Entfernen des animation-name vom Element.
Scroll-gesteuerte Animationen sind CSS-Animationen, die nicht auf der standardmäßigen DocumentTimeline laufen. Stattdessen laufen sie auf einer Scroll-Fortschritts- oder Ansichts-Fortschrittstimeline, die durch das Scrollen des Inhalts eines Elements gesteuert wird. Es gibt eine direkte Verbindung zwischen der Scrollbewegung des Benutzers und dem Fortschritt der Animation entlang der @keyframe-Keyframes. Während der Benutzer nach oben, unten, links oder rechts scrollt, bewegt sich die Animation vorwärts oder rückwärts durch den Fortschritt der Keyframes. Wenn das Scrollen pausiert wird, pausiert die Animation, als ob animation-play-state auf pause gesetzt wäre.
Animationstimelines
Die animation-timeline-Eigenschaft, definiert im Modul CSS-Animationen, wird verwendet, um die für die Animation verwendete Timeline festzulegen.
Das Modul CSS scroll-gesteuerte Animationen definiert Funktionen, um die animation-timeline als Scroll-Fortschritts- oder Ansichts-Fortschrittstimeline festzulegen. Sie können explizit ein Element als Timeline-Controller benennen, indem Sie die Eigenschaften scroll-timeline-* und view-timeline-* verwenden, und dann diesen Namen als animation-timeline eines untergeordneten Elements festlegen. Sie können auch anonyme Scroll-Fortschrittstimelines und anonyme Ansichts-Fortschrittstimelines mit den Funktionen scroll() und view() definieren.
Alternativ kann die animation-timeline-Eigenschaft verwendet werden, um explizit anzugeben, dass die standardmäßige Dokumenten-Timeline verwendet werden soll oder dass die Animation keine Timeline haben soll und daher überhaupt nicht auftreten sollte.
Reguläre CSS-Animationen: Standardmäßige Dokumenten-Timeline
Das explizite Setzen der animation-timeline auf auto oder das Weglassen der Eigenschaft und das Zulassen, dass sie auf auto standardmäßig gesetzt wird, setzt die Timeline auf die standardmäßige Dokumenten-Timeline. Wenn diese standardmäßiger Wert gesetzt ist, wird der Fortschritt der Animation durch die animation-duration, die animation-delay und die verstrichene Zeit seit der Zuordnung der Animation zu dem Element über die Eigenschaft animation-name bestimmt. Die zeitbasierte Dokumenten-Timeline ist die Timeline, die traditionell mit CSS-Animationen assoziiert ist.
:checked ~ .container > .item {
animation-name: action;
animation-duration: 3s;
animation-delay: 500ms;
animation-timeline: auto;
}
Wir erstellen eine Rotations-Keyframe-Animation namens action:
@keyframes action {
from {
rotate: 45deg;
}
to {
rotate: 765deg;
}
}
Wenn das Kontrollkästchen aktiviert ist, wird die action-Animation auf das Element angewendet. Wenn es deaktiviert ist, wird die Animation nicht auf das <div> angewendet.
Versuchen Sie, das Kontrollkästchen zu aktivieren. Während der halben Sekunde Animationsverzögerung passiert nichts. Dann springt das Box-Element, sobald die Animation startet, in eine 45-Grad-Drehung, und es dauert 3 Sekunden, um zusätzliche 720 Grad oder zwei weitere vollständige Umdrehungen zu drehen. Nach insgesamt dreieinhalb Sekunden endet die Animation, und das <div> kehrt in seinen ursprünglichen, nicht rotierten Zustand zurück.
Hinweis:
Die animation-timeline wird durch die animation-Kurzform-Eigenschaft auf den Standardwert auto zurückgesetzt, kann jedoch nicht mit der Kurzform gesetzt werden. Daher sollten Sie bei der Erstellung scroll-gesteuerter Animationen die animation-timeline immer nach allen animation-Kurzformdeklarationen deklarieren, um den gewünschten Effekt zu erzielen.
Scroll-Fortschrittstimelines
Bei einer Scroll-Fortschrittstimeline schreitet die Timeline basierend auf dem Scrollen des scrollbaren Elements (Scroller) von oben nach unten (oder von links nach rechts) und zurück wieder voran. Standardmäßig wird die Position im Scrollbereich in einen prozentualen Fortschritt umgewandelt – 0% am Anfang und 100% am Ende.
Um eine Scroll-Fortschrittstimeline zu erstellen, muss der animation-timeline-Wert den Scroller referenzieren, der benannt oder anonym sein kann.
Benannte Scroll-Fortschrittstimelines
Eine benannte Scroll-Fortschrittstimeline ist eine, bei der der Scroller explizit mithilfe der scroll-timeline-name-Eigenschaft (oder der scroll-timeline-Kurzform) benannt wird. Der Name ist ein <dashed-ident>. Der Scroller wird mit dem zu animierenden Element verknüpft, indem sein scroll-timeline-name als Wert der animation-timeline-Eigenschaft dieses Elements angegeben wird.
Unser HTML enthält drei Elemente: das item, das wir animieren werden; seinen container, den wir scrollen werden; und den Scroller. Der container muss groß genug sein, um seinen scroller-Elternelement zu überlaufen: Wenn es kein Scrollen gibt, wird es keine Scroll-Timeline geben.
<main class="scroller">
<div class="container">
<span class="item"></span>
</div>
</main>
Wir stellen einige grundlegende Stile bereit. Die wichtigen umfassen das Setzen einer Höhe auf den Container, die größer ist als der Scroller, und das Festlegen des Überlaufs zum Scrollen:
.scroller {
width: 400px;
height: 100px;
overflow: scroll;
}
.container {
height: 200px;
}
Das Setzen einer animation-timeline auf das animierte Element, die mit dem scroll-timeline-name eines Elternelements übereinstimmt, ist das, was die benannte Scroll-Fortschrittstimeline erstellt. Wir müssen auch eine Animation einschließen, indem wir den Wert der animation-name-Komponente der animation-Kurzform auf den <custom-ident>-Namen unserer Keyframe-Animation setzen:
.scroller {
scroll-timeline-name: --rotate;
}
.item {
animation: action 1ms linear;
animation-timeline: --rotate;
}
In diesem Fall haben wir kein Kontrollkästchen, da der Fortschritt der action-Animation durch das Scrollen des überfüllenden Scrollers gesteuert wird, der, anders als Zeit, nicht abläuft.
Bevor das Scrollen erfolgt, befindet sich die Position des Containers am oberen Rand des Scrollers, und die Animation befindet sich beim 0%-Keyframe. Versuchen Sie, nach unten zu scrollen. Während Sie scrollen, schreitet die Animation durch die Timeline voran und dreht sich um zusätzliche 720 Grad. Wenn Sie nicht mehr scrollen können, befindet sich der Fortschritt der Animation beim 100%- oder to-Keyframe. Das animierte Element kehrt nicht in seine Standardrotation zurück, es sei denn, der Scroller wird wieder nach oben gescrollt.
Animationsdauer
Sie haben vielleicht bemerkt, dass die animation-duration-Komponente der animation-Kurzform auf 1ms gesetzt wurde. Beim Erstellen von CSS scroll-gesteuerten Animationen beeinflusst das Angeben eines animation-duration-Werts nicht die Dauer der Animation und sollte nicht erforderlich sein. Allerdings können Dauern nicht-lineare Ansichts-Fortschrittstimeline beeinflussen, und Firefox erfordert eine nicht-null animation-duration, um eine Animation auf ein Element anzuwenden. Aus diesen Gründen ist es gängige Praxis, animation-duration auf 1ms zu setzen.
Das Setzen von animation-duration: 1ms stellt sicher, dass die Animation in Firefox funktioniert, der Animationseffekt in allen Browsern konsistent ist und die Animation verborgen ist, wenn ein Browser keine Ansichts-Fortschrittstimeline unterstützt. Wenn der Browser Keyframe-Animationen unterstützt, wird die Animation für den Benutzer nicht sichtbar sein. Die Animation findet jedoch trotzdem statt und Animationsevents werden ausgelöst.
Anonyme Scroll-Fortschrittstimelines
Sie müssen Ihre Scroll-Fortschrittstimeline nicht benennen. Stattdessen können Sie einer Animation eine anonyme Scroll-Fortschrittstimeline zuweisen. In diesem Fall wird die animation-timeline des zu animierenden Elements auf eine scroll()-Funktion gesetzt. Die Funktion wählt den Scroller aus, der die Scroll-Fortschrittstimeline bereitstellt, und die Scroll-Achse, die basierend auf den optionalen Argumenten verwendet werden soll, die Sie an die Funktion übergeben. Ein Parameter ist ein <scroller>-Schlüsselwort, das die Beziehung des Scroller-Elements zum aktuellen Element definiert (nearest, root oder self). Der andere ist der Scrollbalken <axis>](/de/docs/Web/CSS/Reference/Properties/animation-timeline/scroll#axis) Wert (block, inline, y oder x).
Dieses Beispiel verwendet denselben CSS wie das vorherige Beispiel, außer dass die animation-timeline auf eine scroll()-Funktion gesetzt wird. Wir überschreiben auch die Größe des Containers, um die Richtung des Scrolling zu ändern:
.item {
animation: action 1ms linear;
animation-timeline: scroll(nearest inline);
}
.container {
inline-size: 800px;
block-size: 100%;
}
Wir setzen eine inline-size auf den Container, sodass er in der Inline-Richtung überfließt, und setzen die block-size auf 100%, sodass er in der Blockrichtung nicht mehr überfließt. Versuchen Sie, in die Inline-Richtung zu scrollen.
Ansichts-Fortschrittstimelines
Sie können eine Animation auch basierend auf der Sichtbarkeitsänderung eines Elements innerhalb eines Scrollers fortschreiten lassen — dies geschieht über Ansichts-Fortschrittstimelines. Anstatt den Scroll-Offset eines Scroll-Containers zu verfolgen, verfolgen Ansichts-Fortschrittstimelines die relative Position eines Elements, das als Subjekt bezeichnet wird, innerhalb eines Scrollports. Der Fortschritt der Keyframes einer Animation basiert auf der Sichtbarkeit des Subjekts innerhalb des Scrollers. Im Gegensatz zu Scroll-Fortschrittstimelines können Sie bei Ansichts-Fortschrittstimelines den Scroller nicht festlegen – die Sichtbarkeit des Subjekts wird immer innerhalb seines nächstgelegenen Scroller-Vorfahren verfolgt.
Eine Ansichts-Fortschrittstimeline-Animation tritt nur auf, wenn das Element innerhalb seines Scrollports sichtbar ist. Der Fortschritt der Timeline beginnt bei 0%, wenn das verfolgte Subjekt beginnt, den Scrollport an der Block- oder Inline-Endkante zu schneiden. Die 100% treten auf, wenn das Subjekt den Scrollport an der Block- oder Inline-Anfangskante verlässt.
Da die 100% in der Regel erreicht werden, wenn das Element den Viewport verlässt, möchten Sie wahrscheinlich den finalen Effekt Ihrer Animation in einem Keyframe-Block festlegen, der deutlich vor dem Ende der Animation erfolgt. Sie können Ihren abgeschlossenen Effekt innerhalb des 20%-, 50%- oder 80%-Keyframe-Blocks festlegen, anstatt den to- oder 100%-Keyframe zu verwenden, um sicherzustellen, dass das Element die Animation abschließt, während es noch sichtbar ist.
Bei Ansichts-Fortschrittstimelines können Sie den Sichtbarkeitsbereich des Ansichts-Fortschritts anpassen.
Verwenden Sie view-timeline-inset, ein Bestandteil der view-timeline-Kurzform, um anzupassen, wann das Subjekt als im Blick angesehen wird. Der Standardwert ist auto. Die Wirkung eines jeden nicht-auto Einfügewerts ist, als ob Sie die Kanten des Scrollports verschoben hätten: Ein positiver Einfügewert erzeugt eine nach innen gerichtete Anpassung, und ein negativer Wert erzeugt eine nach außen gerichtete Anpassung.
Ähnlich wie bei Scroll-Fortschrittstimelines kann die Ansichts-Fortschrittstimeline benannt oder anonym sein.
Benannte Ansichts-Fortschrittstimeline
Eine benannte Ansichts-Fortschrittstimeline ist eine, bei der das Subjekt explizit mithilfe der view-timeline-name-Eigenschaft benannt wird, einem Bestandteil der view-timeline-Kurzform. Der dashed-ident Name wird dann mit dem zu animierenden Element verknüpft, indem er als Wert der animation-timeline-Eigenschaft dieses Elements angegeben wird.
Bei benannten Ansichts-Fortschrittstimelines muss das zu animierende Element nicht dasselbe wie das Subjekt sein. Mit anderen Worten, das Element, das die Timeline steuert, muss nicht dasselbe sein wie das Element, das animiert wird. Dies bedeutet, dass Sie ein Element basieren auf der Bewegung eines anderen Elements innerhalb seines scrollbaren Containers animieren können.
Hier verwenden wir die view-timeline-name-Eigenschaft, um ein Element zu benennen und es selbst als Quelle einer Ansichts-Fortschrittstimeline zu identifizieren. Wir setzen dann diesen Namen als den Wert der animation-timeline-Eigenschaft fest.
.item {
animation: action 1ms linear;
view-timeline-name: --a-name;
animation-timeline: --a-name;
}
Wir haben die Animation vor der Animationstimeline angewendet, da die animation die animation-timeline auf auto zurücksetzt.
Die Animation ist etwas anders als in den vorherigen Beispielen, da sich der Drehungseffekt bei 20% startet und bei 80% des Wegs durch die Animation endet; dies bedeutet, dass das Element nicht aktiv dreht, wenn es erstmals sichtbar wird, und vor dem vollständigen Verlassen des Blickfelds aufhört, sich zu drehen.
@keyframes action {
0%,
20% {
rotate: 45deg;
}
80%,
100% {
rotate: 720deg;
}
}
Scrollen Sie das Element in den Blick. Beachten Sie, dass das Element durch die @keyframes-Animation animiert, während es sich durch den sichtbaren Bereich seines Vorfahren-Scrollers bewegt.
Anonyme Ansichts-Fortschrittstimeline: die view() Funktion
Alternativ kann eine view()-Funktion als Wert der animation-timeline-Eigenschaft festgelegt werden, um anzugeben, dass die Animation eines Elements auf einer anonymen Ansicht-Fortschrittstimeline basiert. Dies führt dazu, dass das Element basierend auf seiner Position innerhalb seines nächstgelegenen Elternelement-Scrollers animiert wird.
Die view()-Funktion erstellt eine Ansichtstimeline. Sie fügen die Timeline dem Element hinzu, das Sie animieren möchten, unter Verwendung der animation-timeline-Eigenschaft. Die Funktion erstellt eine Ansichtstimeline für jedes durch den Selektor ausgewählte Element.
In diesem Beispiel definieren wir die animation erneut vor der animation-timeline, damit die Timeline nicht zurückgesetzt wird. Dann fügen wir eine view()-Funktion ohne Argumente ein. Wir geben keinen Scroller an, da die Sichtbarkeit des Subjekts definitionsgemäß durch seinen nächstgelegenen Vorfahren-Scroller erfasst wird.
.item {
animation: action 1ms linear;
animation-timeline: view();
}
Parameter der view() Funktion
Die view()-Funktion nimmt bis zu drei optionale Werte als Argumente an:
- Null oder ein
<axis>-Parameter. Wenn gesetzt, gibt dies die Scrollachse an, entlang der die Animation fortschreitet. - Entweder das Schlüsselwort
autooder Null, eins oder zwei<length-percentage>-Einfügewerte. Wenn gesetzt, geben diese Werte die Offsets für den Start und/oder das Ende des Scrollports an.
Das Deklarieren von view() entspricht view(block auto), was block als die Achse des Elternelements definiert, die die Timeline liefert, und die scroll-padding, die allgemein standardmäßig 0 ist, als Einblicke innerhalb des sichtbaren Bereichs, bei dem die Animation startet und endet.
Die Funktion setzt die Werte der view-timeline-axis und view-timeline-inset-Eigenschaften.
Die view-timeline-inset Argumente geben Einsätze (wenn positiv) oder Auslagerungen (wenn negativ) an, die den Anfang und das Ende des Scrollports anpassen. Sie werden verwendet, um die Scrollpositionen zu bestimmen, bei denen das Element als "im Blick" angesehen wird, was die Länge der Animationstimeline bestimmt. Mit anderen Worten, anstatt am Anfangsrand zu starten und am Endrand des Scrollports zu enden, erfolgt die Animation am Anfang und Ende der Einsead-Vereinstellten Ansicht.
Im Gegensatz zur scroll()-Funktion der Scroll-Timeline gibt es kein <scroller>-Argument in der view()-Funktion, da die Sichtbarkeits-Timeline das Subjekt immer innerhalb seines nächstgelegenen Vorfahren-Scrollcontainers verfolgt.
In diesem Beispiel, da wir sie mit Einfügenwerten verwenden, können wir die from und to Keyframe-Selektionsson verwenden.
@keyframes action {
from {
rotate: 45deg;
}
to {
rotate: 720deg;
}
}
.item {
animation: action 1ms linear;
animation-timeline: view(block 20% 20%);
}
Zugänglichkeitsbedenken
Wie bei allen Animationen und Übergängen sollten Sie immer die Präferenz eines Benutzers prefers-reduced-motion berücksichtigen.
Entfernen Sie die Timeline einer Animation
Das Setzen von animation-timeline: none hebt die Zuordnung des Elements zu allen Animationstimelines auf, einschließlich der standardmäßigen zeitbasierten Dokumententimeline, was bedeutet, dass das Element nicht animiert. Während einige Animationen notwendig sein können, können Sie Animationen basierend auf der Einstellung des Benutzers prefers-reduced-motion mit:
@media (prefers-reduced-motion: reduce) {
.optionalAnimations {
animation-timeline: none;
}
}
Da die animation-Kurzform die animation-timeline auf auto setzt, verwenden Sie einen Selektor mit ausreichender Spezifität, um sicherzustellen, dass Ihre animation-timeline nicht durch Ihre animation-Kurzformdeklarationen überschrieben wird.