Back

Détecter l'entrée d'éléments dans la zone d'affichage avec Intersection Observer

Détecter l'entrée d'éléments dans la zone d'affichage avec Intersection Observer

Le suivi de la visibilité des éléments avec des écouteurs d’événements de défilement peut considérablement dégrader les performances de votre site web. Chaque défilement déclenche plusieurs événements, chacun appelant getBoundingClientRect() et forçant des recalculs coûteux du navigateur. L’API Intersection Observer résout ce problème de manière élégante, fournissant une optimisation native du navigateur pour détecter quand des éléments entrent ou sortent de la zone d’affichage.

Points clés à retenir

  • Intersection Observer élimine les goulots d’étranglement de performance causés par les écouteurs d’événements de défilement
  • L’API fonctionne de manière asynchrone, empêchant le blocage du thread principal
  • Un seul observateur peut surveiller efficacement plusieurs éléments
  • L’optimisation native du navigateur offre de meilleures performances que les calculs manuels

Pourquoi les événements de défilement traditionnels sont insuffisants

Les écouteurs d’événements de défilement se déclenchent continuellement pendant le défilement, souvent plus de 60 fois par seconde. Chaque gestionnaire d’événement qui appelle getBoundingClientRect() force le navigateur à recalculer les mises en page, créant des expériences de défilement saccadées. Lorsque plusieurs bibliothèques suivent la visibilité de manière indépendante—pour les publicités, l’analytique et le chargement différé—l’impact sur les performances se multiplie dramatiquement.

L’approche Intersection Observer déplace ces calculs hors du thread principal, permettant au navigateur d’optimiser quand et comment les vérifications d’intersection se produisent.

Comprendre les bases d’Intersection Observer

L’API Intersection Observer surveille de manière asynchrone les éléments cibles qui franchissent les limites avec un élément racine (généralement la zone d’affichage). Au lieu d’un sondage constant, elle vous notifie uniquement lorsque les seuils de visibilité sont franchis.

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      console.log('Element is visible');
    }
  });
});

observer.observe(document.querySelector('.target'));

Le navigateur gère tous les calculs d’intersection en interne, livrant les résultats via un callback avec des objets IntersectionObserverEntry. Chaque entrée fournit isIntersecting (booléen) et intersectionRatio (pourcentage de visibilité de 0 à 1).

Créer votre premier observateur

Configurer un Intersection Observer ne nécessite qu’une fonction de callback et une configuration optionnelle :

const callback = (entries, observer) => {
  entries.forEach(entry => {
    // Propriétés clés disponibles
    console.log({
      isVisible: entry.isIntersecting,
      visibilityRatio: entry.intersectionRatio,
      targetElement: entry.target
    });
  });
};

const options = {
  root: null,        // zone d'affichage
  rootMargin: '0px', // aucun décalage
  threshold: 0.5     // 50% visible
};

const observer = new IntersectionObserver(callback, options);
observer.observe(document.querySelector('.target'));

Le callback reçoit un tableau d’entrées car les observateurs peuvent suivre plusieurs éléments simultanément. La propriété isIntersecting de chaque entrée indique la visibilité actuelle, tandis qu’intersectionRatio fournit le pourcentage de visibilité précis.

Configurer les options de l’observateur

Trois options contrôlent quand les callbacks d’intersection se déclenchent :

root : Définit la zone défilable à surveiller. null utilise la zone d’affichage ; tout élément défilable peut servir de racine personnalisée.

rootMargin : Étend ou réduit la boîte englobante de la racine. Utilisez la syntaxe de marge CSS : "50px" ou "10% 0px". Les valeurs négatives réduisent ; les valeurs positives étendent la zone de détection.

threshold : Pourcentage(s) de visibilité déclenchant les callbacks. Valeur unique : 0.5 (50%). Tableau pour plusieurs déclencheurs : [0, 0.25, 0.5, 0.75, 1].

Surveiller plusieurs éléments efficacement

Une instance d’observateur peut surveiller un nombre illimité d’éléments :

const observer = new IntersectionObserver(callback, options);
const targets = document.querySelectorAll('.lazy-load');

targets.forEach(target => observer.observe(target));

// Arrêter de surveiller des éléments spécifiques
// observer.unobserve(element);

// Arrêter de surveiller tous les éléments
// observer.disconnect();

Ce modèle maximise l’efficacité—le navigateur optimise mieux un seul observateur surveillant des centaines d’éléments que plusieurs observateurs.

Exemples d’implémentation réels

Chargement différé d’images

const imageObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      imageObserver.unobserve(img);
    }
  });
}, { rootMargin: '50px' });

document.querySelectorAll('img[data-src]').forEach(img => {
  imageObserver.observe(img);
});

Déclencher des animations au défilement

const animationObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('animate');
    }
  });
}, { threshold: 0.1 });

document.querySelectorAll('.animate-on-scroll').forEach(element => {
  animationObserver.observe(element);
});

Lecture automatique de vidéos en vue

const videoObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    const video = entry.target;
    if (entry.isIntersecting) {
      video.play();
    } else {
      video.pause();
    }
  });
}, { threshold: 0.5 });

document.querySelectorAll('video').forEach(video => {
  videoObserver.observe(video);
});

Conclusion

L’API Intersection Observer transforme la détection de zone d’affichage d’un goulot d’étranglement de performance en une fonctionnalité optimisée du navigateur. En remplaçant les écouteurs d’événements de défilement par des observateurs d’intersection, vous éliminez le blocage du thread principal tout en gagnant un contrôle de visibilité plus précis. Commencez dès aujourd’hui à migrer votre code de visibilité basé sur le défilement—les navigateurs de vos utilisateurs vous en remercieront.

FAQ

Oui, appelez simplement observer.observe() sur les nouveaux éléments après leur ajout au DOM. La même instance d'observateur peut surveiller des éléments ajoutés à tout moment pendant le cycle de vie de la page.

Le callback se déclenche immédiatement avec l'état d'intersection actuel de l'élément. Cela garantit que vous connaissez toujours le statut de visibilité initial sans avoir besoin de vérifications séparées.

Vérifiez que entry.isIntersecting est false dans votre callback. L'observateur vous notifie à la fois quand les éléments entrent et sortent de la zone observée selon vos paramètres de seuil.

Les navigateurs modernes le prennent en charge nativement. Pour les navigateurs plus anciens comme Internet Explorer, utilisez le polyfill officiel du W3C qui fournit une fonctionnalité identique via JavaScript.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay