Intersection Observer
è una di quelle API probabilmente apprezzate da tutti ed è utilizzabile in tutti
i principali browser. Gli sviluppatori hanno utilizzato questa API per un'ampia gamma di casi d'uso, tra cui
il caricamento differito di immagini e video,
le notifiche quando gli elementi raggiungono position: sticky,
l'attivazione di eventi di analisi
e molti altri.
Nella sua forma più semplice, ecco come appare l'API Intersection Observer v1:
const onIntersection = (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log(entry);
}
}
};
const observer = new IntersectionObserver(onIntersection);
observer.observe(document.querySelector('#some-target'));
Sfide di visibilità in Intersection Observer v1
Con l'API Intersection Observer v1, puoi sapere quando un elemento viene
visualizzato nella finestra. Tuttavia, non puoi determinare se questo elemento è coperto da altri contenuti della pagina, un fenomeno noto come occlusione, o se l'elemento appare modificato dal CSS, ad esempio transform, opacity o filter, il che potrebbe renderlo invisibile.
Per un elemento nel documento di primo livello, queste informazioni possono essere determinate analizzando il DOM con JavaScript, ad esempio con DocumentOrShadowRoot.elementFromPoint().
Al contrario, le stesse informazioni non possono essere ottenute se l'elemento in questione si trova in un iframe di terze parti.
Perché la visibilità è importante?
Purtroppo, su internet ci sono persone malintenzionate. Ad esempio, un publisher disonesto potrebbe utilizzare annunci pay-per-click su un sito web. Potrebbero indurre gli utenti a fare clic su questi annunci per guadagnare di più, almeno finché la rete pubblicitaria non scopre il loro piano. In genere, questi annunci vengono pubblicati negli iframe.
Per ingannare gli utenti, l'editore potrebbe rendere gli iframe dell'annuncio completamente trasparenti
con CSS: iframe { opacity: 0; }. Poi, potrebbero posizionare questi iframe trasparenti
su contenuti accattivanti, come un video di un gatto carino, su cui gli utenti vogliono fare clic.
Questo tipo di attacco si chiama clickjacking.
Puoi vedere un attacco di clickjacking in azione nella sezione superiore della nostra demo. Prova a "guardare" il video del gatto e attiva la modalità trucco. L'annuncio nell'iframe registra i clic come legittimi, anche se hai fatto clic (involontariamente) mentre l'iframe era trasparente.

Miglioramenti di Intersection Observer v2
Intersection Observer v2 può monitorare la "visibilità" di un elemento come la definirebbe
un essere umano. Se imposti un'opzione nel costruttore IntersectionObserver, le istanze IntersectionObserverEntry risultanti includono un nuovo campo booleano denominato isVisible. Quando isVisible
è true, il browser si assicura che l'elemento non sia coperto da altri
contenuti e non abbia effetti visivi che ne nascondano o modifichino la visualizzazione. Se
isVisible è false, il browser non può fornire questa garanzia.
La
specifica
consente falsi negativi: isVisible può essere false anche quando l'elemento è
effettivamente visibile e invariato. Per il rendimento, i browser utilizzano calcoli più semplici,
come i rettangoli di selezione e le forme rettangolari, e non controllano ogni pixel per
dettagli complessi come border-radius.
Tuttavia, i falsi positivi non sono consentiti in nessuna circostanza. Ciò
significa che isVisible non sarà true se l'elemento non è completamente visibile
e non modificato.
Applica queste modifiche
Il costruttore IntersectionObserver ora accetta due proprietà di configurazione aggiuntive:
delayè un numero che indica il ritardo minimo in millisecondi tra le notifiche dell'osservatore per una determinata destinazione.trackVisibilityè un valore booleano che indica se l'osservatore monitorerà le modifiche alla visibilità di un target.
Quando trackVisibility è true, delay deve essere impostato su 100 o su un valore superiore
(ovvero non più di una notifica ogni 100 ms).
Poiché la visibilità è costosa da calcolare, si tratta di una precauzione contro
il degrado delle prestazioni e il consumo della batteria. Gli sviluppatori responsabili dovrebbero
utilizzare il valore di ritardo più elevato tollerabile.
La specifica
calcola la visibilità. Come nella versione 1, quando l'attributo trackVisibility
dell'osservatore è false, la destinazione viene considerata visibile
Nella versione 2, la destinazione viene considerata invisibile se:
Ha una matrice di trasformazione efficace, diversa da una traslazione 2D o da un aumento di scala 2D proporzionale.
Il target o qualsiasi elemento nella relativa catena di blocchi contenitore ha un'opacità effettiva inferiore a 1.0.
Il target o qualsiasi elemento nella relativa catena di blocchi contenitore ha filtri applicati.
Se l'implementazione non può garantire che il target sia completamente non occluso da altri contenuti della pagina.
Ciò significa che le implementazioni attuali sono piuttosto conservative nel garantire la visibilità. Ad esempio, l'applicazione di un filtro in scala di grigi quasi impercettibile
(filter: grayscale(0.01%)) o l'impostazione della trasparenza più piccola
(opacity: 0.99) renderebbe invisibile l'elemento.
Di seguito è riportato un esempio di codice che illustra le nuove funzionalità dell'API. Puoi vedere la logica di monitoraggio dei clic in azione nella seconda sezione della demo. Prova a "guardare" il video del cucciolo. Attiva la modalità di simulazione per trasformarti in un utente malintenzionato e vedere in che modo Intersection Observer v2 impedisce il monitoraggio dei clic sugli annunci non legittimi. Intersection Observer v2 ci protegge.

<!DOCTYPE html>
<!-- This is the ad running in the iframe -->
<button id="callToActionButton">Buy now!</button>
// This is code running in the iframe.
// The iframe must be visible for at least 800ms prior to an input event
// for the input event to be considered valid.
const minimumVisibleDuration = 800;
// Keep track of when the button transitioned to a visible state.
let visibleSince = 0;
const button = document.querySelector('#callToActionButton');
button.addEventListener('click', (event) => {
if ((visibleSince > 0) &&
(performance.now() - visibleSince >= minimumVisibleDuration)) {
trackAdClick();
} else {
rejectAdClick();
}
});
const observer = new IntersectionObserver((changes) => {
for (const change of changes) {
// ⚠️ Feature detection
if (typeof change.isVisible === 'undefined') {
// The browser doesn't support v2, fallback to v1 behavior.
change.isVisible = true;
}
if (change.isIntersecting && change.isVisible) {
visibleSince = change.time;
} else {
visibleSince = 0;
}
}
}, {
threshold: [1.0],
// 🆕 Track the actual visibility of the element
trackVisibility: true,
// 🆕 Set a minimum delay between notifications
delay: 100
}));
// Require that the entire iframe be visible.
observer.observe(document.querySelector('#ad'));
Risorse aggiuntive
- Bozza di lavoro dell'Intersection Observer.
- Intersection Observer v2 su Stato della piattaforma Chrome.
Ringraziamenti
Grazie a Simeon Vincent, Yoav Weiss e Mathias Bynens per la revisione, nonché a Stefan Zager per la revisione e l'implementazione della funzionalità in Chrome.