Erste Schritte mit scrollbaren Animationen in CSS

1. Hinweis

Mit scrollbasierten 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ückgeblendet wird. Außerdem können Sie mit scrollbasierten Animationen eine Animation basierend auf der Position eines Elements innerhalb seines Scrollcontainers steuern. So lassen sich interessante Effekte wie ein Parallaxe-Hintergrundbild, Fortschrittsbalken beim Scrollen und Bilder erstellen, die sich erst zeigen, wenn sie in den Blick kommen.

Neu in Chrome 115 ist die Unterstützung einer Reihe von JavaScript-Klassen und CSS-Eigenschaften, mit denen Sie ganz einfach deklarative scrollbasierte Animationen erstellen können. Diese neuen APIs funktionieren in Verbindung mit den vorhandenen Web Animations APIs und CSS Animations APIs.

In diesem Codelab erfahren Sie, wie Sie mit 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 einen Paralax-Hintergrundeffekt mit einer Scroll-Zeitachse in CSS.
  • So erstellen Sie in CSS eine Fortschrittsanzeige mit einer Scroll-Zeitachse.
  • So erstellen Sie einen Bild-Entfaltungseffekt mit einer Ansichtszeitachse in CSS.
  • So legen Sie in CSS ein Targeting auf verschiedene Arten von Bereichen einer Wiedergabezeitachse fest.

Voraussetzungen

Eine der folgenden Gerätekombinationen:

  • Eine aktuelle Version von Chrome (115 oder höher) unter ChromeOS, macOS oder Windows, bei der die Option „Experimentelle Webplattformfunktionen“ aktiviert ist.
  • Grundlegende Kenntnisse von HTML
  • Grundlegende Kenntnisse von CSS, insbesondere von CSS-Animationen

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 npm nicht installiert ist, können Sie die src/index.html-Datei auch in Chrome öffnen.

3. Informationen zu Zeitachsen für Animationen

Standardmäßig wird eine an ein Element angehängte Animation in der Zeitleiste des Dokuments wiedergegeben. Das bedeutet, dass die Animation beim Laden der Seite mit der Zeit fortschreitet. Dies ist die Standard-Animationszeitachse und bis jetzt die einzige Animationszeitachse, auf die Sie Zugriff hatten.

Mit scrollbasierten Animationen haben Sie Zugriff auf zwei neue Arten von Zeitleisten:

  • Zeitachse für den Fortschritt scrollen
  • Zeitachse für den Fortschritt ansehen

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

Zeitachse für den Fortschritt scrollen

Eine Scroll-Fortschritts-Zeitachse ist eine Animations-Zeitachse, die mit dem Fortschritt der Scrollposition eines Scroll-Containers (auch Scrollport oder Scroller genannt) entlang einer bestimmten Achse verknüpft ist. Hiermit wird eine Position in einem Scrollbereich in einen Prozentsatz des Fortschritts entlang einer Zeitachse umgewandelt.

Die Startposition der Bildlaufleiste steht für 0% Fortschritt und die Endposition für 100 %. In der folgenden Visualisierung wird der Fortschritt von 0% auf 100% gezählt, während Sie den Schieberegler nach unten bewegen.

Zeitachse für den Fortschritt ansehen

Diese Art von Zeitachse ist mit dem relativen Fortschritt eines bestimmten Elements innerhalb eines Scrollcontainers verknüpft. Genau wie bei einer Scroll-Fortschrittsleiste wird der Scroll-Offset eines Scrollers erfasst. Im Gegensatz zu einer Zeitleiste für den Scrollvorgang wird der Fortschritt hier durch die relative Position eines Motivs innerhalb des Scrollers bestimmt. Dies ist vergleichbar mit IntersectionObserver, mit dem erfasst wird, wie viel eines Elements im Scroller sichtbar ist. Wenn das Element im Scroller nicht sichtbar ist, überschneidet es sich nicht. Wenn es im Scroller sichtbar ist, auch nur der kleinste Teil, überschneidet es sich.

Eine Zeitachse für den Wiedergabefortschritt beginnt in dem Moment, in dem ein Motiv mit dem Scroller übereinstimmt, und endet, wenn das Motiv nicht mehr mit dem Scroller übereinstimmt. In der folgenden Visualisierung sehen Sie, dass der Fortschritt von 0% beginnt, wenn das Motiv den Scrollcontainer betritt, und 100% erreicht, wenn es den Scrollcontainer verlässt.

Standardmäßig wird eine Animation, die mit der Zeitleiste für den Wiedergabefortschritt verknüpft ist, auf den gesamten Bereich angewendet. Dieser Zeitraum beginnt, wenn das Motiv in den Scrollbereich eintritt, und endet, wenn es ihn verlässt.

Sie können sie auch mit einem bestimmten Teil der Zeitachse für den Fortschritt der Wiedergabe verknüpfen, indem Sie den Bereich angeben, an den sie angehängt werden soll. Das kann beispielsweise nur der Fall sein, wenn das Motiv in den Scrollbereich eintritt. In der folgenden Visualisierung beginnt der Fortschritt bei 0 %, wenn das Motiv in den Scrollcontainer eintritt, erreicht aber bereits 100 %, sobald es vollständig überschneidet.

Die möglichen Zeiträume für die Wiedergabeliste, auf die Sie Ihre Anzeigen 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, können Sie unter https://goo.gle/view-timeline-range-tool nachsehen, was die einzelnen Bereiche bedeuten.

4. Parallaxen-Hintergrundeffekt erstellen

Der erste Effekt, den wir der Seite hinzufügen, ist ein Paralax-Hintergrundeffekt auf dem Haupthintergrundbild. Wenn Sie auf der Seite nach unten scrollen, sollte sich das Hintergrundbild bewegen, allerdings mit einer anderen Geschwindigkeit. Dazu verwenden Sie eine Zeitleiste für den Scrollvorgang.

Dazu sind zwei Schritte erforderlich:

  1. Erstellen Sie eine Animation, bei der sich die Position des Hintergrundbilds ändert.
  2. Verknüpfen Sie die Animation mit dem Scrollvorgang des Dokuments.

Animation erstellen

  1. Verwenden Sie zum Erstellen der Animation eine normale Reihe von Keyframes. Verschieben Sie 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 diese Keyframes jetzt dem Body-Element hinzu:

src/styles.css

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

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

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

Die Funktion scroll() akzeptiert ein <scroller>- und ein <axis>-Argument.

Zulässige Werte für das Argument <scroller>:

  • nearest: Es wird der nächste übergeordnete Scrollcontainer verwendet (Standard).
  • root. Der Dokument-Viewport wird als Scrollcontainer verwendet.
  • self: Das Element selbst wird als Scrollcontainer verwendet.

Zulässige Werte für das Argument <axis>:

  • block: Es wird der Fortschritt entlang der Blockachse des Scrollcontainers verwendet (Standard).
  • inline. Der Fortschritt wird anhand der Inline-Achse des Scroll-Containers gemessen.
  • y. Der Fortschritt wird anhand der Y-Achse des Scrollcontainers gemessen.
  • x. Der Fortschritt wird anhand der X-Achse des Scrollcontainers gemessen.

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

  • Legen Sie scroll(root block) als Wert für die Eigenschaft animation-timeline im Textkörper fest.
  • Außerdem macht eine animation-duration in Sekunden keinen Sinn. Legen Sie daher eine Dauer von 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 Stamm-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 richtig gelaufen ist, sollte das Ergebnis so aussehen:

Falls nicht, prüfe den Codezweig solution-step-1.

5. Fortschrittsanzeige für die Bildergalerie erstellen

Auf der Seite befindet sich ein horizontales Karussell, für das eine Fortschrittsanzeige erforderlich ist, um anzugeben, 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 Frames 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 das .gallery__progress-Element mit einer Scroll-Fortschrittsanzeige Wie im vorherigen Schritt gezeigt, können Sie dazu eine anonyme Zeitachse für den Scrollvorgang mit der Funktion scroll() erstellen:

src/styles.css

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

Dieser Code funktioniert zwar auf den ersten Blick, aber aufgrund der Funktionsweise der automatischen Suche nach Scrollcontainern mit nearest funktioniert er nicht. 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 darauf angewendet wurde. Das bedeutet, dass das .gallery__scrollcontainer-Element, also der Schieberegler, auf den ausgerichtet werden soll, bei dieser automatischen Suche überhaupt nicht berücksichtigt wird.

Um dieses Problem zu umgehen, erstellen Sie im Element .gallery__scrollcontainer eine benannte Zeitachse für den Scrollvorgang und verknüpfen Sie die .gallery__progress mit diesem Namen.

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

Da die Galerie horizontal scrollt, müssen Sie auch die Property scroll-timeline-axis festlegen. Zulässige Werte sind dieselben wie für das <axis>-Argument von scroll().

Um die Animation mit der Scroll-Fortschritts-Zeitachse zu verknüpfen, legen Sie für das Element, das animiert werden soll, die animation-timeline-Eigenschaft auf denselben Wert wie die für die scroll-timeline-name verwendete Kennung fest.

  • Ä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 richtig funktioniert hat, sollte das Ergebnis so aussehen:

Falls nicht, prüfe den Codezweig solution-step-2.

6. Galeriebilder beim Ein- und Ausblenden im Scrollbereich animieren

Zeitachse für den Fortschritt einer anonymen Wiedergabe einrichten

Ein schöner Effekt ist es, die Galeriebilder einzublenden, wenn sie in den Blick kommen. Dazu können Sie eine Zeitachse für den Wiedergabefortschritt verwenden.

Mit der Funktion view() können Sie eine Zeitachse für den Fortschritt der Wiedergabe erstellen. Zulässige Argumente sind <axis> und <view-timeline-inset>.

  • <axis> ist mit dem Wert aus der Zeitachse für den Scrollvorgang identisch und definiert, welche Achse erfasst werden soll.
  • Mit <view-timeline-inset> können Sie einen positiven oder negativen Versatz angeben, um die Grenzen anzupassen, wenn ein Element als sichtbar oder nicht sichtbar eingestuft wird.
  • Die keyframes sind bereits vorhanden. Sie müssen sie nur anhängen. Erstellen Sie dazu für jedes .gallery__entry-Element eine Zeitachse für den Wiedergabefortschritt.

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);
}

Zeitachse für den Fortschritt einer Wiedergabe begrenzen

Wenn Sie das CSS speichern und die Seite laden, sehen Sie, dass die Elemente einblenden, aber etwas stimmt nicht. Sie beginnen bei einer Deckkraft von 0, wenn sie vollständig außer Sicht sind, und enden erst bei einer Deckkraft von 1, wenn sie vollständig verschwunden sind.

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

  1. Wenn Sie die Animation nur auf den entry-Bereich des Motivs ausrichten möchten, verwenden Sie die CSS-Eigenschaft animation-range, um festzulegen, 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 läuft jetzt von entry 0% (das Motiv betritt den Scroller) bis entry 100% (das Motiv ist vollständig im Scroller).

Folgende Zeitachsenbereiche sind verfügbar:

  • cover: Stellt den gesamten Bereich der Zeitachse für den Fortschritt der Wiedergabe dar.
  • entry: Der Bereich, in dem das Hauptfeld in den Sichtbarkeitsbereich für den Fortschritt der Wiedergabe eintritt.
  • exit: Der Bereich, in dem das Hauptfeld den Sichtbarkeitsbereich des Fortschritts der Ansicht verlässt.
  • entry-crossing: Stellt den Bereich dar, in dem das Hauptfeld den Endrand des Rahmens schneidet.
  • exit-crossing: Stellt den Bereich dar, in dem der Hauptbereich den Startrand schneidet.
  • contain: Der Bereich, in dem sich das Hauptfeld entweder vollständig innerhalb des Sichtbarkeitsbereichs des Wiedergabefortschritts im Scrollbereich befindet oder diesen vollständig bedeckt. Das hängt davon ab, ob das Motiv höher oder kürzer als der Scroller ist.

Unter https://goo.gle/view-timeline-range-tool können Sie sehen, was die einzelnen Bereiche darstellen und wie sich die Prozentsätze auf die Start- und Endpositionen auswirken.

  1. Da hier Start- und Endbereich identisch sind und die Standardabweichungen verwendet werden, vereinfachen Sie animation-range zu einem einzelnen Namen für den Animationsabschnitt:

src/styles.css

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry;
}
  • Wenn Sie die Bilder ausblenden möchten, sobald sie den Scroller verlassen, können Sie dasselbe wie bei der Einblendungsanimation tun, aber auf einen anderen Bereich ausrichten.

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 Bereich entry und die animate-out-Keyframes auf den Bereich exit angewendet.

Änderungen prüfen

Wenn alles richtig funktioniert hat, sollte das Ergebnis so aussehen:

Falls nicht, prüfe den Codezweig solution-step-3.

7. Galeriebilder mithilfe eines Satzes von Frames animieren, wenn sie den Scrollbereich betreten und verlassen

Ein Satz von Keyframes

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

Die Form der Frames sieht so aus:

@keyframes keyframes-name {
  range-name range-offset {
    ...
  }
  range-name range-offset {
    ...
  }
}
  1. So kombinierst du 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 vorhanden 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 richtig funktioniert hat, sollten Sie dasselbe Ergebnis wie im vorherigen Schritt erhalten. Falls nicht, prüfe den Codezweig solution-step-4.

8. Glückwunsch!

Sie haben dieses Codelab abgeschlossen und wissen jetzt, wie Sie Zeitleisten für den Scroll- und den Seitenaufbau in CSS erstellen.

Weitere Informationen

Ressourcen: