Découvrez "IntersectionObserver"

Les IntersectionObservers vous permettent de savoir quand un élément observé entre dans la fenêtre d'affichage du navigateur ou en sort.

Browser Support

  • Chrome: 51.
  • Edge: 15.
  • Firefox: 55.
  • Safari: 12.1.

Source

Imaginons que vous souhaitiez suivre le moment où un élément de votre DOM entre dans la fenêtre d'affichage visible. Vous pouvez le faire pour charger les images de manière différée juste à temps ou parce que vous devez savoir si l'utilisateur regarde réellement une certaine bannière publicitaire. Pour ce faire, vous pouvez associer l'événement de défilement ou utiliser un minuteur périodique et appeler getBoundingClientRect() sur cet élément.

Toutefois, cette approche est extrêmement lente, car chaque appel à getBoundingClientRect() force le navigateur à recalculer la mise en page de l'intégralité de la page, ce qui entraîne des à-coups considérables sur votre site Web. Les choses deviennent presque impossibles lorsque vous savez que votre site est chargé dans un iframe et que vous souhaitez savoir quand l'utilisateur peut voir un élément. Le modèle d'origine unique et le navigateur ne vous permettent pas d'accéder aux données de la page Web qui contient l'iFrame. C'est un problème courant pour les annonces, par exemple, qui sont fréquemment chargées à l'aide d'iFrames.

IntersectionObserver a été conçu pour rendre ce test de visibilité plus efficace, et il est désormais disponible dans tous les navigateurs récents. IntersectionObserver vous permet de savoir quand un élément observé entre dans la fenêtre d'affichage du navigateur ou en sort.

Visibilité de l'iFrame

Comment créer une IntersectionObserver

L'API est plutôt petite et peut être décrite à l'aide d'un exemple :

const io = new IntersectionObserver(entries => {
  console.log(entries);
}, {
  /* Using default options. Details below */
});

// Start observing an element
io.observe(element);

// Stop observing an element
// io.unobserve(element);

// Disable entire IntersectionObserver
// io.disconnect();

Si vous utilisez les options par défaut pour IntersectionObserver, votre rappel sera appelé à la fois lorsque l'élément apparaît partiellement et lorsqu'il quitte complètement la fenêtre d'affichage.

Si vous devez observer plusieurs éléments, il est possible et conseillé de le faire en utilisant la même instance IntersectionObserver en appelant observe() plusieurs fois.

Un paramètre entries est transmis à votre rappel, qui est un tableau d'objets IntersectionObserverEntry. Chaque objet contient des données d'intersection mises à jour pour l'un des éléments observés.

🔽[IntersectionObserverEntry]
    time: 3893.92
    🔽rootBounds: ClientRect
        bottom: 920
        height: 1024
        left: 0
        right: 1024
        top: 0
        width: 920
    🔽boundingClientRect: ClientRect
    // ...
    🔽intersectionRect: ClientRect
    // ...
    intersectionRatio: 0.54
    🔽target: div#observee
    // ...

rootBounds est le résultat de l'appel de getBoundingClientRect() sur l'élément racine, qui est la fenêtre d'affichage par défaut. boundingClientRect est le résultat de getBoundingClientRect() appelé sur l'élément observé. intersectionRect est l'intersection de ces deux rectangles et vous indique efficacement quelle partie de l'élément observé est visible. intersectionRatio est étroitement lié et vous indique dans quelle mesure l'élément est visible. Grâce à ces informations, vous pouvez désormais implémenter des fonctionnalités telles que le chargement juste-à-temps des éléments avant qu'ils ne deviennent visibles à l'écran. efficacement.

Ratio d'intersection.

Les IntersectionObserver fournissent leurs données de manière asynchrone, et votre code de rappel s'exécute dans le thread principal. De plus, la spécification indique que les implémentations IntersectionObserver doivent utiliser requestIdleCallback(). Cela signifie que l'appel au rappel que vous avez fourni est de faible priorité et qu'il sera effectué par le navigateur pendant les périodes d'inactivité. Il s'agit d'une décision de conception délibérée.

Divs à défilement

Je ne suis pas un grand fan du défilement dans un élément, mais je ne suis pas là pour juger, et IntersectionObserver non plus. L'objet options accepte une option root qui vous permet de définir une alternative à la fenêtre d'affichage comme racine. Il est important de garder à l'esprit que root doit être un ancêtre de tous les éléments observés.

Intersectez tout ce que vous voulez !

Non ! Mauvais développeur ! Cela ne constitue pas une utilisation raisonnée des cycles de processeur de l'utilisateur. Prenons l'exemple d'un défilement infini : dans ce scénario, il est vivement conseillé d'ajouter des sentinelles au DOM, puis de les observer (et de les recycler). Vous devez ajouter un élément sentinelle à proximité du dernier élément du défilement infini. Lorsque cette sentinelle apparaît, vous pouvez utiliser le rappel pour charger des données, créer les éléments suivants, les associer au DOM et repositionner la sentinelle en conséquence. Si vous recyclez correctement la sentinelle, aucun appel supplémentaire à observe() n'est nécessaire. Le IntersectionObserver continue de fonctionner.

Défilement infini

Plus d'actualités, s'il vous plaît

Comme mentionné précédemment, le rappel sera déclenché une fois lorsque l'élément observé apparaîtra partiellement, et une autre fois lorsqu'il aura quitté la fenêtre d'affichage. De cette façon, IntersectionObserver vous donne une réponse à la question "L'élément X est-il visible ?". Toutefois, dans certains cas d'utilisation, cela peut ne pas suffire.

C'est là qu'intervient l'option threshold. Il vous permet de définir un tableau de seuils intersectionRatio. Votre rappel sera appelé chaque fois que intersectionRatio franchira l'une de ces valeurs. La valeur par défaut de threshold est [0], ce qui explique le comportement par défaut. Si nous remplaçons threshold par [0, 0.25, 0.5, 0.75, 1], nous recevrons une notification chaque fois qu'un quart supplémentaire de l'élément devient visible :

Animation du seuil.

D'autres options ?

Pour l'instant, il n'existe qu'une seule option supplémentaire par rapport à celles listées ci-dessus. rootMargin vous permet de spécifier les marges de la racine, ce qui vous permet d'agrandir ou de réduire la zone utilisée pour les intersections. Ces marges sont spécifiées à l'aide d'une chaîne de style CSS, comme "10px 20px 30px 40px", qui spécifie respectivement les marges supérieure, droite, inférieure et gauche. En résumé, la structure d'options IntersectionObserver propose les options suivantes :

new IntersectionObserver(entries => {/* … */}, {
  // The root to use for intersection.
  // If not provided, use the top-level document's viewport.
  root: null,
  // Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
  // If an explicit root element is specified, components may be percentages of the
  // root element size.  If no explicit root element is specified, using a
  // percentage is an error.
  rootMargin: "0px",
  // Threshold(s) at which to trigger callback, specified as a ratio, or list of
  // ratios, of (visible area / total area) of the observed element (hence all
  // entries must be in the range [0, 1]).  Callback will be invoked when the
  // visible ratio of the observed element crosses a threshold in the list.
  threshold: [0],
});

<iframe> magique

Les IntersectionObserver ont été conçus spécifiquement pour les services publicitaires et les widgets de réseaux sociaux, qui utilisent fréquemment des éléments <iframe> et pourraient bénéficier de savoir s'ils sont visibles. Si un <iframe> observe l'un de ses éléments, le défilement du <iframe> et le défilement de la fenêtre contenant le <iframe> déclencheront le rappel aux moments appropriés. Toutefois, dans ce dernier cas, rootBounds sera défini sur null pour éviter les fuites de données entre les origines.

Qu'est-ce que IntersectionObserver n'est pas ?

N'oubliez pas que IntersectionObserver n'est intentionnellement ni parfait au pixel près, ni à faible latence. Les utiliser pour implémenter des tâches telles que des animations dépendantes du défilement est voué à l'échec, car les données seront, à proprement parler, obsolètes au moment où vous les utiliserez. Le document explicatif fournit plus de détails sur les cas d'utilisation d'origine de IntersectionObserver.

Quelle quantité de travail puis-je effectuer dans le rappel ?

En bref : si vous passez trop de temps dans le rappel, votre application sera lente. Toutes les pratiques courantes s 'appliquent.

Allez-y et croisez vos éléments

La compatibilité de IntersectionObserver avec les navigateurs est bonne, car elle est disponible dans tous les navigateurs récents. Si nécessaire, un polyfill peut être utilisé dans les anciens navigateurs. Il est disponible dans le dépôt du WICG. Évidemment, vous ne bénéficierez pas des avantages de performances qu'une implémentation native vous offrirait en utilisant ce polyfill.

Vous pouvez commencer à utiliser IntersectionObserver dès maintenant. Dites-nous ce que vous avez trouvé.