Eingangs- und Ausgangseffekte sind Animationen, die ausgelöst werden, wenn ein Element in den Darstellungsbereich eintritt oder ihn verlässt. Damit lassen sich ansprechende und dynamische Nutzererlebnisse schaffen. Sie können beispielsweise einen Eingangseffekt verwenden, um ein Element einzublenden, wenn es in den sichtbaren Bereich gescrollt wird, oder einen Ausgangseffekt, um es zu verkleinern, wenn es aus dem sichtbaren Bereich gescrollt wird.
Implementierung
Wenn Sie einem Element Ein- und Ausstiegseffekte hinzufügen möchten, müssen Sie mehrere CSS-Eigenschaften kombinieren. Im Folgenden erhalten Sie eine ausführliche Anleitung:
Erstellen Sie separate
@keyframesfür die Ein- und Ausblendanimationen. Die Eingangsanimation wird angewendet, wenn das Element in den Darstellungsbereich eingeblendet wird, und die Ausgangsanimation, wenn es ausgeblendet wird.@keyframes slide-in { from { transform: translateX(-100%); } } @keyframes slide-out { to { transform: translateX(100%); } }Hängen Sie die Keyframes für den Ein- und Ausstieg an das Element an. Dazu definieren Sie mehrere Animationen im Attribut
animation.- Geben Sie der Eingangsanimation einen
animation-fill-mode-Wert vonbackwards, damit der Anfangszustand vor dem Start der Animation angewendet wird. - Geben Sie der Ausgangsanimation einen
animation-fill-modevonforwards, damit sie nach Abschluss der Animation ihren Endzustand beibehält.
.animated-element { animation: slide-in 1s linear backwards, slide-out 1s linear forwards; }- Geben Sie der Eingangsanimation einen
Erstellen Sie eine ViewTimeline und verknüpfen Sie sie mit den Animationen. Eine View Timeline ist eine Art von Zeitachse, die mit der Sichtbarkeit eines Elements im Darstellungsbereich verknüpft ist. Sie können eine mit der Funktion
view()erstellen und sie dann mit der Propertyanimation-timelineauf Ihre Animationen anwenden..animated-element { animation-timeline: view(); }Standardmäßig verfolgt
view()das Element auf derblock-Achse. Wenn Sie die Bewegung auf derinline-Achse verfolgen müssen, können Sieview(inline)verwenden.Beschränken Sie die Animationen auf die Bereiche
entryundexit. Mit der Propertyanimation-rangekönnen Sie angeben, in welchem Teil der Zeitachse eine Animation ausgeführt werden soll.- Der Bereich
entrydeckt die Zeit ab, die vergeht, bis das Element vollständig sichtbar ist, nachdem es zum ersten Mal im Darstellungsbereich angezeigt wurde. - Der Bereich
exitdeckt die Zeit ab, in der das Element den Darstellungsbereich verlässt, bis es vollständig ausgeblendet ist.
.animated-element { animation-range: entry, exit; }- Der Bereich
Beispielcode
Mit diesem Code werden die direkten untergeordneten Elemente des Scrollers beim Scrollen mithilfe einer anonymen Ansichtszeitachse animiert:
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: view(inline);
animation-range: entry, exit;
}
}
}
Wenn die Elemente in den Scrollport gelangen, wird die Animation grow abgespielt. Wenn sie den Scrollport verlassen, wird die Animation shrink abgespielt.
Der folgende Code hat dasselbe visuelle Ergebnis, animiert aber die direkten untergeordneten Elemente des Scrollers beim Scrollen mit einer benannten view-timeline:
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
view-timeline: --tl inline;
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: --tl;
animation-range: entry, exit;
}
}
}
Best Practices
Wenn Sie scrollgesteuerte Animationen verwenden, sollten Sie einige Best Practices beachten, um eine reibungslose und barrierefreie Nutzung zu ermöglichen:
- DO include feature detection: Not all browsers support scroll-driven animations. Verwenden Sie
@supports ((animation-timeline: view()) and (animation-range: entry)), um die Unterstützung zu prüfen, und stellen Sie einen Fallback für Browser bereit, die die Funktion nicht unterstützen.- Die
(animation-range: entry)-Prüfung MUSS hier enthalten sein, um Browser mit nur teilweiser Unterstützung herauszufiltern. - Verwenden Sie für die Fallback-Strategie NICHT das Paket
scroll-timeline-polyfill, da es nicht vollständig ist und viele bekannte Probleme aufweist. - Wenn die Animation nur dekorativ ist, entscheide dich für die progressive Verbesserung und stelle KEIN Fallback bereit.
- Die
- DO respect user preferences: Some users prefer to have less motion on the web. Verwenden Sie die Medienabfrage
prefers-reduced-motion, um Ihre Animationen für diese Nutzer zu deaktivieren oder zu reduzieren. - DO try to animate only performant CSS properties: For the smoothest animations, stick to animating properties that can be handled by the browser's compositor thread, such as
transformandopacity. Das Animieren anderer Attribute wiewidthoderheightkann zu Leistungsproblemen führen. - RICHTIG: Verwenden Sie die richtige Deklarationsreihenfolge. Wenn Sie die Kurzschreibweise
animationverwenden, deklarieren Sieanimation-timelinedanach, um zu verhindern, dass die Kurzschreibweise die Zeitachse zurücksetzt.
Wenn Sie die Funktion view() verwenden, um eine scrollbasierte Animation zu erstellen, gilt Folgendes:
- OPTIONAL: Geben Sie die zu verfolgende Achse explizit an. Wenn Sie nicht die Standardachse
blockverwenden (z. B. bei einem horizontalen Scroller), geben Sie mitview(block)oderview(inline)explizit an, welche Achse verfolgt werden soll. - Wenn die Animation nicht auf das verfolgte Subjekt selbst angewendet wird, verwenden Sie eine benannte Ansichtszeitachse.
Wenn Sie die Eigenschaft view-timeline verwenden, um eine scrollbasierte Animation zu erstellen:
- Verwenden Sie für den Namen ein CSS-
<dashed-ident>. (EMPFOHLEN) - OPTIONAL: Achte darauf, die zu verfolgende Achse explizit anzugeben. Wenn du nicht die Standardachse
blockverwendest (z. B. bei einem horizontalen Scroller), gib explizit an, welche Achse mitview-timeline-axisverfolgt werden soll. - DO: Achten Sie darauf, dass der Suchbereich funktioniert. Wenn das Element, das die
view-timelinedeklariert, kein flacher Baum-Ancestor des animierten Elements ist, erhöhen Sie die Sichtbarkeit des Namens derview-timeline, indem Sietimeline-scopefür einen gemeinsamen Ancestor verwenden.
Bevorzugen Sie ein benanntes view-timeline, wenn mehrere Elemente oder untergeordnete Elemente des verfolgten Objekts animiert werden müssen.
Browserunterstützung und Fallback-Strategien
Daher ist in der Regel eine Fallback-Strategie erforderlich.
Für Browser, die keine scrollgesteuerten Animationen unterstützen, können Sie einen Fallback verwenden, um die visuellen Effekte nachzubilden. Die Fallbacks werden in der Regel entweder mit einem Scroll-Listener (für ScrollTimeline-Effekte) oder der IntersectionObserver API (für ViewTimeline-Effekte) erstellt.
Verwenden Sie in Browsern mit integrierter Unterstützung für scrollgesteuerte Animationen IMMER die native CSS-Implementierung, da diese leistungsfähiger ist.
Beachten Sie, dass nicht jeder Effekt mit dem Fallback-Ansatz nachgebildet werden kann.
Speziell für diesen Anwendungsfall wird im folgenden Script der Fallback für Browser angewendet, die keine scrollgesteuerten Animationen unterstützen. Es wird ein IntersectionObserver verwendet, um die Sichtbarkeit des .wrapper-Elements zu verfolgen, und die transform-Eigenschaft der Ebenen wird basierend auf der Scrollposition aktualisiert.
<script>
if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
// This matches the effect as defined in the CSS example above.
// Customize this further if needed.
entry.target.style.scale = 0.5 + entry.intersectionRatio * 0.5;
}
},
{
threshold: Array.from({ length: 101 }, (_, i) => i / 100),
}
);
document.querySelectorAll('.scroller > *').forEach((el) => {
observer.observe(el);
});
}
</script>