Elemente beim Scrollen einblenden mit IntersectionObserver
Bilder erst laden, wenn sie sichtbar werden, oder Abschnitte sanft einblenden – ganz ohne Scroll-Event-Gehacke. Der IntersectionObserver macht das effizient und in wenigen Zeilen.
„Blende die Abschnitte ein, sobald man hinscrollt" – so ein Effekt sieht auf einer Website edel aus. Früher hätte man dafür bei jedem scroll-Event Positionen ausgerechnet – das ruckelt und kostet Leistung. Heute nehme ich den IntersectionObserver: Der Browser sagt mir selbst Bescheid, wenn ein Element in den sichtbaren Bereich kommt.
Einblenden beim Scrollen
Erst das CSS für den sanften Übergang:
.reveal { opacity: 0; transform: translateY(24px); transition: opacity .6s, transform .6s; }
.reveal.is-visible { opacity: 1; transform: none; }Dann der Observer – er beobachtet alle .reveal-Elemente und schaltet die Klasse um, sobald sie auftauchen:
const io = new IntersectionObserver((entries, obs) => {
for (const entry of entries) {
if (!entry.isIntersecting) continue;
entry.target.classList.add('is-visible');
obs.unobserve(entry.target); // einmal reicht – spart Arbeit
}
}, {
threshold: 0.1, // ab 10 % Sichtbarkeit auslösen
rootMargin: '0px 0px -10% 0px', // etwas früher, bevor es ganz unten ist
});
document.querySelectorAll('.reveal').forEach(el => io.observe(el));Bilder erst laden, wenn sie gebraucht werden
Dasselbe Prinzip spart Ladezeit: Das echte Bild steckt in data-src und wird erst gesetzt, wenn das Bild fast im Blick ist.
<img data-src="/gross/foto.webp" alt="" class="lazy">const imgObserver = new IntersectionObserver((entries, obs) => {
for (const entry of entries) {
if (!entry.isIntersecting) continue;
const img = entry.target;
img.src = img.dataset.src;
obs.unobserve(img);
}
}, { rootMargin: '200px' }); // 200 px vorher laden, damit nichts „poppt"
document.querySelectorAll('img.lazy').forEach(img => imgObserver.observe(img));Der Trick mit unobserve() ist wichtig: Sobald ein Element erledigt ist, hört der Observer auf, es zu beobachten – so bleibt die Seite auch bei hundert Elementen flüssig. Und loading="lazy" am <img> gibt es zwar nativ, aber der Observer gibt dir die volle Kontrolle über den Zeitpunkt und den Effekt.
So einen dezenten Scroll-Effekt baue ich auch in Kundenseiten ein. Wenn du eine schnelle, moderne Website brauchst, meld dich über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
requestAnimationFrame – die Animationsschleife, die zum Bildschirm passt
setInterval(schritt, 16) läuft auf einem 144-Hz-Monitor anders als auf einem alten Handy – und im Hintergrundtab einfach weiter. requestAnimationFrame löst beides, wenn man die verstrichene Zeit mitrechnet statt Bilder zu zählen.
toSorted, toReversed und with: Arrays sortieren, ohne das Original zu zerstören
array.sort() sortiert nicht eine Kopie, sondern das Array selbst – und genau daran ist schon mancher Zustand im Frontend stillschweigend kaputtgegangen. Seit ES2023 gibt es zu jeder dieser Methoden eine Variante, die eine Kopie zurückgibt.
Aufzählungen richtig verketten mit Intl.ListFormat
"a, b und c" von Hand zusammenzubauen geht fast immer schief – bei einem Element, bei zwei Elementen, beim letzten Komma. Intl.ListFormat macht es richtig, in jeder Sprache, ganz ohne Bibliothek.