Erste Schritte mit scrollbaren Animationen in CSS

1. Hinweis

Mit scrollgesteuerten Animationen können Sie die Wiedergabe einer Animation basierend auf der Scrollposition eines Scrollcontainers steuern. Das bedeutet, dass die Animation beim Scrollen nach oben oder unten vor- oder zurückgespult wird. Außerdem können Sie mit scrollgesteuerten Animationen eine Animation basierend auf der Position eines Elements in seinem Scroll-Container steuern. So können Sie interessante Effekte wie ein Parallax-Hintergrundbild, Fortschrittsbalken und Bilder erstellen, die sich erst zeigen, wenn sie in den Blick kommen.

In Chrome 115 wird eine Reihe von JavaScript-Klassen und CSS-Eigenschaften unterstützt, mit denen Sie ganz einfach deklarative scrollgesteuerte Animationen erstellen können. Diese neuen APIs funktionieren in Verbindung mit den vorhandenen Web Animations- und CSS Animations-APIs.

In diesem Codelab erfahren Sie, wie Sie mithilfe von CSS scrollgesteuerte Animationen erstellen. In diesem Codelab lernen Sie die vielen neuen CSS-Properties kennen, die mit dieser spannenden Funktion eingeführt wurden, z. B. scroll-timeline, view-timeline, animation-timeline und animation-range.

Lerninhalte

  • So erstellen Sie mit einer Scroll-Zeitleiste in CSS einen Parallax-Hintergrundeffekt.
  • So erstellen Sie einen Fortschrittsbalken mit einer Scroll-Zeitleiste in CSS.
  • So erstellen Sie mit einer View Timeline in CSS einen Bild-Reveal-Effekt.
  • Verschiedene Arten von Bereichen einer Ansichtszeitachse in CSS ausrichten

Voraussetzungen

Eine der folgenden Gerätekonfigurationen:

  • Eine aktuelle Version von Chrome (115 oder höher) unter ChromeOS, macOS oder Windows, bei der das Flag „Experimental Web Platform Features“ aktiviert ist.
  • Grundlegende HTML-Kenntnisse
  • Grundlegendes Verständnis von CSS, insbesondere von Animationen in CSS

2. Einrichten

Alles, was Sie für dieses Projekt benötigen, ist in einem GitHub-Repository verfügbar. Klonen Sie zuerst den Code und öffnen Sie ihn in Ihrer bevorzugten Entwicklungsumgebung.

  1. Öffnen Sie einen neuen Browsertab und rufen Sie https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab auf.
  2. Klonen Sie das Repository.
  3. Öffnen Sie den Code in Ihrer bevorzugten IDE.
  4. Führen Sie npm install aus, um die Abhängigkeiten zu installieren.
  5. Führen Sie npm start aus und rufen Sie http://localhost:3000/ auf.
  6. Wenn Sie npm nicht installiert haben, können Sie die Datei src/index.html auch in Chrome öffnen.

3. Informationen zu Animationszeitachsen

Standardmäßig wird eine Animation, die einem Element zugewiesen ist, auf der Dokument-Zeitachse ausgeführt. Das bedeutet, dass die Animation beim Laden der Seite mit der Zeit voranschreitet. Das ist die Standard-Animationszeitachse und war bisher die einzige Animationszeitachse, auf die Sie Zugriff hatten.

Mit scrollgesteuerten Animationen haben Sie Zugriff auf zwei neue Arten von Zeitachsen:

  • Scrollen auf der Fortschritts-Zeitachse
  • Fortschrittszeitachse ansehen

In CSS können diese Zeitachsen mithilfe der Eigenschaft animation-timeline an eine Animation angehängt werden. Sehen Sie sich an, was diese neuen Zeitpläne bedeuten und wie sie sich voneinander unterscheiden.

Scrollen auf der Fortschritts-Zeitachse

Eine Scrollfortschritt-Zeitachse ist eine Animationszeitachse, die mit dem Fortschritt der Scrollposition eines Scrollcontainers (auch Scrollport oder Scroller genannt) entlang einer bestimmten Achse verknüpft ist. Wandelt eine Position in einem Scrollbereich in einen Prozentsatz des Fortschritts auf einer Zeitachse um.

Die Startposition für den Bildlauf entspricht 0% Fortschritt und die Endposition für den Bildlauf entspricht 100% Fortschritt. In der folgenden Visualisierung wird der Fortschritt von 0% bis 100% angezeigt, wenn Sie im Scroller nach unten scrollen.

Fortschrittszeitachse ansehen

Diese Art von Zeitachse ist mit dem relativen Fortschritt eines bestimmten Elements in einem Scrollcontainer verknüpft. Wie bei einer Scroll-Fortschritts-Zeitachse wird der Scroll-Offset eines Scrollers erfasst. Im Gegensatz zu einer Scroll-Fortschritts-Zeitachse wird der Fortschritt hier durch die relative Position eines Elements innerhalb des Scrollers bestimmt. Das ist vergleichbar mit IntersectionObserver, mit dem erfasst wird, wie lange ein Element im Scroller sichtbar ist. Wenn das Element nicht im Scroller sichtbar ist, überschneidet es sich nicht. Wenn es im Scroller sichtbar ist, auch wenn es sich nur um den kleinsten Teil handelt, überschneidet es sich.

Eine Zeitachse für die Ansicht beginnt, wenn sich ein Motiv mit dem Scroller überschneidet, und endet, wenn sich das Motiv nicht mehr mit dem Scroller überschneidet. In der folgenden Visualisierung sehen Sie, dass der Fortschritt ab 0% gezählt wird, wenn das Motiv in den Scrollcontainer eintritt, und 100% erreicht, wenn es den Scrollcontainer verlässt.

Standardmäßig wird eine mit der Zeitachse für den Fortschritt der Ansicht verknüpfte Animation an den gesamten Bereich angehängt. Sie beginnt, wenn das Motiv in den Scrollport eintritt, und endet, wenn es ihn verlässt.

Sie können sie auch mit einem bestimmten Teil der Zeitachse für den Fortschritt verknüpfen, indem Sie den Bereich angeben, an den sie angehängt werden soll. Das kann beispielsweise nur dann der Fall sein, wenn das Motiv in den Scroller eintritt. In der folgenden Visualisierung beginnt der Fortschritt bei 0 %, wenn das Motiv in den Scroll-Container eintritt. Er erreicht jedoch bereits 100 %, sobald das Motiv vollständig sichtbar ist.

Die möglichen Bereiche für den View-Zeitachsentyp, auf die Sie ausrichten können, sind cover, contain, entry, exit, entry-crossing und exit-crossing. Diese Bereiche werden später in diesem Codelab erläutert. Wenn Sie es nicht abwarten können, verwenden Sie das Tool unter https://goo.gle/view-timeline-range-tool, um zu sehen, was die einzelnen Bereiche darstellen.

4. Parallaxen-Hintergrundeffekt erstellen

Der erste Effekt, der der Seite hinzugefügt werden soll, ist ein Parallax-Hintergrund für das Haupt-Hintergrundbild. Wenn Sie auf der Seite nach unten scrollen, sollte sich das Hintergrundbild bewegen, allerdings mit einer anderen Geschwindigkeit. Dazu verwenden Sie eine Scroll-Fortschritts-Zeitachse.

Dazu sind zwei Schritte erforderlich:

  1. Erstellen Sie eine Animation, mit der die Position des Hintergrundbilds geändert wird.
  2. Verknüpfen Sie die Animation mit dem Scrollverlauf des Dokuments.

Animation erstellen

  1. Verwenden Sie zum Erstellen der Animation einen regulären Satz von Keyframes. Verschieben Sie darin die Hintergrundposition vertikal von 0% auf 100%:

src/styles.css

@keyframes move-background {
  from {
    background-position: 50% 0%;
  }
  to {
    background-position: 50% 100%;
  }
}
  1. Fügen Sie nun die Keyframes dem Body-Element hinzu:

src/styles.css

body {
  animation: 1s linear move-background;
}

Mit diesem Code wird die Animation move-background dem body-Element hinzugefügt. Die animation-duration-Property ist auf eine Sekunde festgelegt und es wird eine linear-Beschleunigung verwendet.

Am einfachsten lässt sich eine Zeitachse für den Scrollfortschritt mit der Funktion scroll() erstellen. Dadurch wird eine anonyme Scrollfortschritt-Zeitachse erstellt, die Sie als Wert für die Eigenschaft animation-timeline festlegen können.

Die Funktion scroll() akzeptiert die Argumente <scroller> und <axis>.

Für das <scroller>-Argument sind die folgenden Werte zulässig:

  • nearest: Verwendet den nächsten übergeordneten Scrollcontainer (Standard).
  • root: Verwendet den Dokument-Viewport als Scroll-Container.
  • self: Das Element selbst wird als Scroll-Container verwendet.

Für das <axis>-Argument sind die folgenden Werte zulässig:

  • block: Hier wird das Maß für den Fortschritt entlang der Blockachse des Scroll-Containers verwendet (Standard).
  • inline: Hier wird der Fortschritt entlang der Inline-Achse des Scroll-Containers gemessen.
  • y: Hier wird der Fortschritt entlang der y-Achse des Scroll-Containers verwendet.
  • x: Hier wird das Maß für den Fortschritt entlang der X-Achse des Scroll-Containers verwendet.

Wenn Sie die Animation mit dem Stamm-Scroller auf der Blockachse verknüpfen möchten, müssen Sie die Werte root und block an scroll() übergeben. Zusammen ergibt sich der Wert scroll(root block).

  • Legen Sie scroll(root block) als Wert für die Eigenschaft animation-timeline im Textkörper fest.
  • Da eine animation-duration in Sekunden keinen Sinn ergibt, legen Sie die Dauer auf auto fest. Wenn Sie keinen animation-duration angeben, wird standardmäßig auto verwendet.

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(root block);
}

Da der Root-Scroller auch der nächste übergeordnete Scroller für das Body-Element ist, können Sie auch den Wert nearest verwenden:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(nearest block);
}

Da nearest und block die Standardwerte sind, können Sie sie auch weglassen. In diesem Fall kann der Code so vereinfacht werden:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll();
}

Änderungen prüfen

Wenn alles wie geplant verlaufen ist, sollten Sie jetzt Folgendes haben:

Falls nicht, sehen Sie sich den solution-step-1-Zweig des Codes an.

5. Fortschrittsanzeige für die Bildergalerie erstellen

Auf der Seite befindet sich ein horizontales Karussell, für das eine Fortschrittsanzeige erforderlich ist, um anzuzeigen, welches Foto gerade angezeigt wird.

Das Markup für das Karussell sieht so aus:

src/index.html

<div class="gallery">
  <div class="gallery__scrollcontainer" style="--num-images: 3;">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
  </div>
</div>

Die Keyframes für die Fortschrittsanzeige sind bereits vorhanden und sehen so aus:

src/styles.css

@keyframes adjust-progress {
  from {
    transform: scaleX(calc(1 / var(--num-images)));
  }
  to {
    transform: scaleX(1);
  }
}

Diese Animation muss an dasgallery__progress-Element mit einer Zeitachse für den Scrollfortschritt. Wie im vorherigen Schritt gezeigt, können Sie dies erreichen, indem Sie mit der Funktion scroll() eine anonyme Scroll-Fortschritts-Zeitachse erstellen:

src/styles.css

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  animation-timeline: scroll(nearest inline);
}

Dieser Code scheint zwar zu funktionieren, tut es aber nicht, weil die automatische Suche nach Scrollcontainern mit nearest nicht wie erwartet funktioniert. Beim Suchen nach dem nächsten Scroller werden nur die Elemente berücksichtigt, die sich auf die Position des Elements auswirken können. Da .gallery__progress absolut positioniert ist, ist das erste übergeordnete Element, das seine Position bestimmt, das .gallery-Element, da position: relative angewendet wurde. Das bedeutet, dass das .gallery__scrollcontainer-Element, also der Scroller, der als Ziel festgelegt werden muss, bei dieser automatischen Suche überhaupt nicht berücksichtigt wird.

Um dieses Problem zu umgehen, erstellen Sie eine benannte Zeitachse für den Scrollfortschritt für das .gallery__scrollcontainer-Element und verknüpfen Sie das .gallery__progress-Element über diesen Namen damit.

Wenn Sie eine benannte Scroll-Fortschritts-Zeitachse für ein Element erstellen möchten, legen Sie die CSS-Eigenschaft scroll-timeline-name für den Scroll-Container auf einen beliebigen Wert fest. Der Wert muss mit -- beginnen.

Da die Galerie horizontal gescrollt wird, müssen Sie auch das Attribut scroll-timeline-axis festlegen. Die zulässigen Werte sind dieselben wie für das <axis>-Argument von scroll().

Um die Animation mit der Zeitachse für den Scrollfortschritt zu verknüpfen, legen Sie die Eigenschaft animation-timeline für das zu animierende Element auf denselben Wert wie die Kennung fest, die für scroll-timeline-name verwendet wird.

  • Ändern Sie die Datei styles.css so, dass sie Folgendes enthält:

src/styles.css

.gallery__scrollcontainer {
  /* Create the gallery-is-scrolling timeline */
  scroll-timeline-name: --gallery-is-scrolling;
  scroll-timeline-axis: inline;
}

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  /* Set gallery-is-scrolling as the timeline */
  animation-timeline: --gallery-is-scrolling;
}

Änderungen prüfen

Wenn alles wie geplant verlaufen ist, sollten Sie jetzt Folgendes haben:

Falls nicht, sehen Sie sich den solution-step-2-Zweig des Codes an.

6. Galeriebilder beim Ein- und Ausblenden im Scrollport animieren

Anonyme Fortschritts-Zeitachse einrichten

Ein schöner Effekt ist das Einblenden der Galeriebilder, wenn sie in den Darstellungsbereich kommen. Dazu können Sie eine Fortschrittszeitachse verwenden.

Mit der Funktion view() können Sie eine Zeitachse für den Ansichtsfortschritt erstellen. Die zulässigen Argumente sind <axis> und <view-timeline-inset>.

  • <axis> ist dasselbe wie in der Zeitachse für den Scrollfortschritt und definiert, welche Achse erfasst werden soll.
  • Mit <view-timeline-inset> können Sie einen positiven oder negativen Offset angeben, um die Grenzen anzupassen, wenn ein Element als sichtbar oder nicht sichtbar gilt.
  • Die Keyframes sind bereits vorhanden, Sie müssen sie nur noch anhängen. Erstellen Sie dazu für jedes .gallery__entry-Element eine Zeitachse für den Fortschritt.

src/styles.css

@keyframes animate-in {
  from {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  to {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Bereich einer Fortschrittszeitachse für Ansichten begrenzen

Wenn Sie das CSS speichern und die Seite laden, werden die Elemente eingeblendet. Etwas scheint jedoch nicht zu stimmen. Sie beginnen mit der Deckkraft 0, wenn sie vollständig außerhalb des Sichtfelds sind, und enden erst mit der Deckkraft 1, wenn sie vollständig verschwunden sind.

Das liegt daran, dass der Standardbereich für eine Zeitachse für den Fortschritt einer Ansicht der gesamte Bereich ist. Dies wird als cover-Bereich bezeichnet.

  1. Wenn Sie nur den entry-Bereich des Motivs anvisieren möchten, verwenden Sie die CSS-Eigenschaft animation-range, um einzuschränken, wann die Animation ausgeführt werden soll.

src/styles.css

.gallery__entry {
  animation: linear fade-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry 0% entry 100%;
}

Die Animation wird jetzt von entry 0% (das Motiv ist kurz davor, in den Scroller einzutreten) bis entry 100% (das Motiv ist vollständig in den Scroller eingetreten) ausgeführt.

Folgende Zeitachsenbereiche sind möglich:

  • cover: Stellt den gesamten Bereich der Zeitachse für den Fortschritt der Ansicht dar.
  • entry: Der Bereich, in dem das Hauptfeld in den Sichtbarkeitsbereich für den Fortschritt der Ansicht eintritt.
  • exit: Der Bereich, in dem das Hauptkonto aus dem Sichtbarkeitsbereich für den Fortschritt der Ansicht entfernt wird.
  • entry-crossing: Stellt den Bereich dar, in dem das Hauptfeld die Endgrenze überschreitet.
  • exit-crossing: Der Bereich, in dem das Hauptfeld die Startgrenze überschreitet.
  • contain: Stellt den Bereich dar, in dem das Hauptfeld entweder vollständig im Sichtbarkeitsbereich des Ansichtsfortschritts im Scrollport enthalten ist oder diesen vollständig abdeckt. Das hängt davon ab, ob das Motiv größer oder kleiner als der Scroller ist.

Mit dem Tool unter https://goo.gle/view-timeline-range-tool können Sie sehen, wofür die einzelnen Bereiche stehen und wie sich die Prozentsätze auf die Start- und Endpositionen auswirken.

  1. Da die Start- und Endbereiche hier identisch sind und die Standard-Offsets verwendet werden, kann animation-range auf einen einzelnen Namen für den Animationsbereich vereinfacht werden:

src/styles.css

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry;
}
  • Wenn Sie die Bilder beim Verlassen des Scrollers ausblenden möchten, können Sie genauso vorgehen wie bei der Animation zum Einblenden, aber einen anderen Bereich festlegen.

src/styles.css

@keyframes animate-out {
  from {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  to {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in, linear animate-out;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry, exit;
}

Die animate-in-Keyframes werden auf den entry-Bereich und die animate-out-Keyframes auf den exit-Bereich angewendet.

Änderungen prüfen

Wenn alles wie geplant verlaufen ist, sollten Sie jetzt Folgendes haben:

Falls nicht, sehen Sie sich den solution-step-3-Zweig des Codes an.

7. Galeriebilder beim Ein- und Ausblenden in den Scrollport animieren – mit einem Satz von Keyframes

Argumente für einen Satz von Keyframes

Anstatt zwei Animationen an unterschiedliche Bereiche anzuhängen, können Sie einen Satz von Keyframes erstellen, der bereits die Bereichsinformationen enthält.

Die Form der Keyframes sieht so aus:

@keyframes keyframes-name {
  range-name range-offset {
    ...
  }
  range-name range-offset {
    ...
  }
}
  1. So kombinieren Sie die Keyframes für das Ein- und Ausblenden:

src/styles.css

@keyframes animate-in-and-out {
  entry 0% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  entry 90% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }

  exit 10% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  exit 100% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}
  1. Wenn die Bereichsinformationen in den Keyframes enthalten sind, müssen Sie animation-range nicht mehr separat angeben. Hängen Sie die Keyframes als animation-Property an.

src/styles.css

.gallery__entry {
  animation: linear animate-in-and-out both;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Änderungen prüfen

Wenn alles geklappt hat, sollten Sie dasselbe Ergebnis wie im vorherigen Schritt erhalten. Falls nicht, sehen Sie sich den solution-step-4-Zweig des Codes an.

8. Glückwunsch!

Sie haben dieses Codelab abgeschlossen und wissen jetzt, wie Sie Scroll- und View-Fortschrittszeitachsen in CSS erstellen.

Weitere Informationen

Ressourcen: