Signatur
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 alsCSSNumericValue, bei der die Timeline beginnt.endOffset: die Scroll-Position alsCSSNumericValue, 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
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%"
});
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,startOffsetundendOffsetsindCSSNumericValue-Objekte in Prozent bzw. Pixeln, keine Millisekunden. Bei fehlendem Layout oder einer inaktiven Timeline istcurrentTimenull.- Die Dauer einer Animation auf einer Scroll-Timeline ist
auto. Werte fürdurationin Millisekunden verändern nur die Verhältnisse vondelayundendDelay, aber nicht das Scroll-Verhalten. - Gibt es keinen scrollbaren Vorfahren oder ist
subjectnicht gerendert (etwa beidisplay: none), ist die Timeline inaktiv. - Animiere nach Möglichkeit nur
transformundopacity. Nur diese Eigenschaften laufen auf dem Compositor-Thread. - Nimm Rücksicht auf
prefers-reduced-motionund schalte starke Bewegungseffekte bei Bedarf ab.