Ein Header, der beim Scrollen kleiner wird, ist ein gängiges UI-Muster, bei dem ein fixiertes Header-Element oben auf der Seite beim Scrollen nach unten fließend verkleinert wird. Dieser Effekt wird häufig verwendet, um den Platz auf dem Bildschirm für den Hauptinhalt zu maximieren und gleichzeitig wichtige Navigations- oder Markenelemente zugänglich zu halten. Mit scrollgesteuerten CSS-Animationen lässt sich dieser Effekt deklarativ und leistungsstark erzielen, indem eine Animation mit der Scrollposition des Dokuments verknüpft wird.
Implementierung
So erstellen Sie einen Header, der beim Scrollen kleiner wird:
Fixierten Header erstellen: Beginnen Sie mit einem Header-Element, das oben auf der Seite fixiert ist und eine vordefinierte Höhe hat.
<header>HEADER</header>header { position: fixed; height: 200px; top: 0; left: 0; right: 0; }Animation zum Verkleinern definieren: Erstellen Sie eine CSS-Animation, die die Höhe des Headers ändert.
@keyframes shrink { to { height: 50px; } }Animation anwenden und Zeitachse scrollen: Hängen Sie die Animation an den Header an und verwenden Sie die Funktion
scroll(), um sie mit der Scrollposition des Dokuments zu verknüpfen.header { animation: shrink auto linear both; animation-timeline: scroll(block root); }animation-rangefestlegen: Verwenden Sie die Propertyanimation-range, um die Scroll-Distanz anzugeben, über die die Animation erfolgen soll. Wenn Sie beispielsweise den Header über die ersten 150 Pixel des Scrollens verkleinern möchten, verwenden Sieanimation-range: 0px 150px;.header { animation-range: 0px 150px; }
Tipp: Damit der Inhalt nach dem Header nicht von diesem verdeckt wird, fügen Sie dem body (oder dem Hauptinhaltscontainer) ein padding-top hinzu, das der ursprünglichen Höhe des Headers entspricht.
Tipp: Damit der Inhalt der Seite synchron mit dem kleiner werdenden Header gescrollt wird, legen Sie für animation-range-end die Differenz zwischen der Anfangs- und der Endgröße fest. So wird die Animation genau dann abgeschlossen, wenn der Header seine endgültige Größe erreicht hat. In dieser Demo wird der Header von 200px auf 50px verkleinert, sodass animation-range-end auf 150px gesetzt wird.
Beispielcode
@keyframes shrink {
to {
height: 50px;
}
}
header {
animation: shrink auto linear both;
animation-timeline: scroll(block root);
animation-range: 0px 150px;
}
Best Practices
Wenn Sie scrollbasierte 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: scroll()) and (animation-range: 0% 100%)), 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: 0% 100%)-Prüfung MUSS hier enthalten sein, um Browser mit nur teilweiser Unterstützung herauszufiltern. - Verwenden Sie NICHT das Paket
scroll-timeline-polyfillfür die Fallback-Strategie, 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-timelineundanimation-rangedanach, um zu verhindern, dass die Kurzschreibweise die Zeitachse zurücksetzt.
Wenn Sie die Funktion scroll() verwenden, um eine scrollbasierte Animation zu erstellen, gilt Folgendes:
- OPTIONAL: Geben Sie den Scroller explizit an. Wenn Sie nicht den nächstgelegenen übergeordneten Scroller verwenden möchten, geben Sie mit
scroll(root)oderscroll(self)explizit an, welchen Scroller Sie verwenden möchten.- Wenn
root,nearestoderselfnicht ausreichen, verwenden Sie eine benannte Scroll-Zeitachse.
- Wenn
- OPTIONAL: Geben Sie die zu verfolgende Achse explizit an. Wenn Sie nicht die Standardachse
blockverwenden (z. B. bei einem horizontalen Scroller), geben Sie mitscroll(block)oderscroll(inline)explizit an, welche Achse verfolgt werden soll.
In diesem speziellen Anwendungsfall gilt Folgendes:
- Das Element, das Sie animieren, DARF NICHT
position: staticoderposition: relativesein, wenn Sie Prozentwerte inanimation-rangeverwenden.- Das liegt daran, dass diese Elemente als „In-Flow“ betrachtet werden. Wenn diese Elemente beim Scrollen verkleinert werden, verringert sich die gesamte Scroll-Distanz, was sich auf den berechneten Wert von beispielsweise
10%beim Scrollen auswirkt.
- Das liegt daran, dass diese Elemente als „In-Flow“ betrachtet werden. Wenn diese Elemente beim Scrollen verkleinert werden, verringert sich die gesamte Scroll-Distanz, was sich auf den berechneten Wert von beispielsweise
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 Scroll-Listener verwendet, um die Scrollposition des Dokuments über eine Distanz von 150px zu verfolgen und die Höhe des Headers entsprechend zu aktualisieren.
// Fallback for browsers that don't support scroll-driven animations
if (!CSS.supports('(animation-timeline: scroll()) and (animation-range: 0% 100%)')) {
const header = document.querySelector('header');
const initialHeight = 200;
const finalHeight = 50;
const scrollDistance = 150;
window.addEventListener('scroll', () => {
const scrollY = window.scrollY;
const scrollPercent = Math.min(1, scrollY / scrollDistance);
const newHeight = initialHeight - (initialHeight - finalHeight) * scrollPercent;
header.style.height = `${newHeight}px`;
});
}