Start · Sprachen · JavaScript · Referenz · ViewTimeline

ViewTimeline

Schnittstelle

Stellt eine Timeline dar, deren Fortschritt davon abhängt, wie weit ein Element (<code>subject</code>) durch den sichtbaren Bereich seines Scroll-Containers gewandert ist.

seit JavaScript Chrome/Edge 115+, Safari 26+; Firefox nur hinter F Kategorie: webapi

Signatur

interface ViewTimeline extends ScrollTimeline

Beschreibung

ViewTimeline gehört zur Web Animations API und ist das JavaScript-Gegenstück zur CSS-Eigenschaft view-timeline bzw. zur Funktion view() in animation-timeline. Anders als eine normale DocumentTimeline läuft die Zeit hier nicht in Millisekunden ab. Der Fortschritt ergibt sich stattdessen aus der Sichtbarkeit eines Elements: Er liegt bei 0 %, wenn das Element gerade in den Scrollport eintritt, und bei 100 %, wenn es ihn ganz verlassen hat.

ViewTimeline erbt von ScrollTimeline. Zu den geerbten Eigenschaften source (der nächste Scroll-Container des Elements) und axis kommen drei eigene, schreibgeschützte Eigenschaften hinzu:

  • subject: das beobachtete Element.
  • startOffset: die Scroll-Position als CSSNumericValue, bei der die Timeline beginnt.
  • endOffset: die Scroll-Position als CSSNumericValue, bei der die Timeline endet.

Typische Einsatzfälle sind Einblend-Effekte beim Hereinscrollen, Parallax-Bilder, Fortschrittsanzeigen für einzelne Abschnitte und „Reveal“-Animationen. Früher brauchte man dafür einen IntersectionObserver oder scroll-Listener. Die Animation läuft hier oft auf dem Compositor-Thread und damit ruckelfrei.

Die übergebene Timeline wird meist mit rangeStart und rangeEnd in Element.animate() kombiniert. Damit legt man fest, in welchem Abschnitt der Sichtbarkeit die Animation laufen soll. Mögliche Bereiche sind cover, contain, entry, exit, entry-crossing und exit-crossing.

Parameter

Name Typ Default Beschreibung
$options object {} Konfigurationsobjekt für den Konstruktor new ViewTimeline(options).
$options.subject Element null Das Element, dessen Sichtbarkeit im nächsten Scroll-Vorfahren den Fortschritt bestimmt.
$options.axis "block" | "inline" | "x" | "y" "block" Die Scroll-Achse, die ausgewertet wird. block und inline richten sich nach der Schreibrichtung.
$options.inset string | Array<CSSNumericValue | "auto"> "auto" Rückt die Ränder des Scrollports nach innen (positiv) oder außen (negativ), z. B. "100px 20%". Entspricht der CSS-Eigenschaft view-timeline-inset.

Rückgabewert

Typ
ViewTimeline
Beschreibung
Eine neue ViewTimeline-Instanz. Man kann sie als timeline-Option an Element.animate() oder an new Animation() übergeben.

Beispiele

Karte beim Hereinscrollen einblenden

const card = document.querySelector('.card');

// Timeline an die Sichtbarkeit der Karte koppeln
const timeline = new ViewTimeline({ subject: card, axis: 'block' });

card.animate(
  [
    { opacity: 0, transform: 'translateY(40px)' },
    { opacity: 1, transform: 'translateY(0)' }
  ],
  {
    timeline,
    fill: 'both',
    rangeStart: 'entry 0%',   // beginnt, sobald die Karte unten auftaucht
    rangeEnd: 'entry 100%'    // endet, wenn sie ganz sichtbar ist
  }
);

Eigenschaften einer ViewTimeline auslesen

const section = document.querySelector('#features');
const timeline = new ViewTimeline({ subject: section, inset: '0px 100px' });

// Werte stehen erst nach dem Layout bereit
requestAnimationFrame(() => {
  console.log(timeline.subject === section);
  console.log(timeline.source);                 // nächster Scroll-Container
  console.log(timeline.axis);
  console.log(timeline.startOffset.toString()); // z. B. "820px"
  console.log(timeline.endOffset.toString());   // z. B. "1640px"
  console.log(timeline.currentTime?.toString()); // z. B. "12.5%"
});
true <html>…</html> block 820px 1640px 12.5%

Funktionsprüfung mit Fallback über IntersectionObserver

const images = document.querySelectorAll('.parallax img');

if ('ViewTimeline' in window) {
  images.forEach((img) => {
    img.animate(
      { transform: ['translateY(-15%)', 'translateY(15%)'] },
      { timeline: new ViewTimeline({ subject: img }), fill: 'both', rangeStart: 'cover 0%', rangeEnd: 'cover 100%' }
    );
  });
} else {
  // Einfacher Fallback: nur einblenden
  const io = new IntersectionObserver((entries) => {
    entries.forEach((e) => e.target.classList.toggle('visible', e.isIntersecting));
  });
  images.forEach((img) => io.observe(img));
}

// Wichtig · Fallstricke

Browser-Unterstützung: Chromium-Browser unterstützen die Schnittstelle ab Version 115, Safari ab 26. In Firefox ist sie nur hinter einem Flag verfügbar (layout.css.scroll-driven-animations.enabled). Prüfe deshalb mit 'ViewTimeline' in window, ob sie vorhanden ist, und sieh einen Fallback vor. Alternativ gibt es ein Polyfill (scroll-timeline).

  • currentTime, startOffset und endOffset sind CSSNumericValue-Objekte in Prozent bzw. Pixeln, keine Millisekunden. Bei fehlendem Layout oder einer inaktiven Timeline ist currentTime null.
  • Die Dauer einer Animation auf einer Scroll-Timeline ist auto. Werte für duration in Millisekunden verändern nur die Verhältnisse von delay und endDelay, aber nicht das Scroll-Verhalten.
  • Gibt es keinen scrollbaren Vorfahren oder ist subject nicht gerendert (etwa bei display: none), ist die Timeline inaktiv.
  • Animiere nach Möglichkeit nur transform und opacity. Nur diese Eigenschaften laufen auf dem Compositor-Thread.
  • Nimm Rücksicht auf prefers-reduced-motion und schalte starke Bewegungseffekte bei Bedarf ab.