Intersection Observer v2 agrega la capacidad no solo de observar las intersecciones per se, sino también de detectar si el elemento de intersección era visible en el momento de la intersección.
Intersection Observer v1 es una de esas APIs que probablemente han sido amadas a nivel universal y, ahora que
Safari también lo admite,
Finalmente, también se puede usar universalmente
en los navegadores más importantes. Para hacer un repaso rápido de la API,
Te recomiendo ver los videos de Surma
Micropropina supercargada en la intersección
Observador v1 que está incorporado a continuación.
También puedes leer los textos de
artículo.
Se usó Intersection Observer v1 para una amplia variedad de casos de uso, como
carga diferida de imágenes y videos,
recibir notificaciones cuando los elementos llegan a position: sticky
,
activar eventos de análisis,
y mucho más.
Para conocer todos los detalles, consulta la Documentos de Intersection Observer en MDN, pero a modo de recordatorio, así es como se ve la API de Intersection Observer v1 en la caso básico:
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'));
¿Cuál es el desafío de Intersection Observer v1?
Para ser claros, Intersection Observer v1 es excelente, pero no es perfecto. Existen
algunos casos excepcionales en los que la API no funciona. Analicemos este tema con más detalle.
La API de Intersection Observer v1 puede indicarte cuando un elemento se desplaza en la
viewport de la ventana, pero no indica si el elemento está cubierto
por cualquier otro contenido de la página (es decir, cuando el elemento está oculto) o si
la visualización del elemento se modificó con efectos visuales como transform
, opacity
,
filter
, etc., que puede hacerlo invisible de forma efectiva.
Para un elemento del documento de nivel superior, esta información se puede determinar
el DOM a través de JavaScript, por ejemplo, a través de
DocumentOrShadowRoot.elementFromPoint()
y, luego, profundizar.
Por el contrario, no se puede obtener la misma información si el elemento en cuestión es
ubicadas en un iframe de terceros.
¿Por qué es tan importante la visibilidad real?
Desafortunadamente, Internet es un lugar que atrae a personas que actúan de mala fe con peores intenciones.
Por ejemplo, se podría incentivar a un publicador sospechoso que publica anuncios de pago por clic en un sitio de contenido
engañar a los usuarios para que hagan clic en sus anuncios y, así, aumentar el pago que recibe el publicador (al menos,
por un período breve, hasta que la red de publicidad los detecte).
Por lo general, este tipo de anuncios se publican en iframes.
Si el editor quisiera que los usuarios
hicieran clic en esos anuncios, podría crear
Es completamente transparente mediante la aplicación de una regla de CSS iframe { opacity: 0; }
y la superposición de los iframes.
además de algo atractivo, como el video de un gato lindo en el que los usuarios querrían hacer clic.
Esto se denomina clickjacking.
Puede ver un ataque de clickjacking en acción en la sección superior de esta
demo (intenta "mirar" el video del gato)
y activa el "modo truco").
Notará que el anuncio en el iframe "piensa" recibió clics legítimos, incluso si
sea completamente transparente cuando haces clic (fingir
involuntariamente).
¿Cómo se soluciona este problema con Intersection Observer v2?
Intersection Observer v2 introduce el concepto de hacer un seguimiento de la "visibilidad" real de un objetivo
elemento como lo definiría un ser humano.
Al establecer una opción
Constructor IntersectionObserver
,
intersecciones
IntersectionObserverEntry
las instancias contendrán un nuevo campo booleano llamado isVisible
.
Un valor de true
en isVisible
es una sólida garantía de la implementación subyacente
que el elemento de destino no está oculto en su totalidad por otro contenido
y no tiene efectos visuales aplicados que puedan alterar o distorsionar su visualización en pantalla.
Por el contrario, un valor false
significa que la implementación no puede garantizarlo.
Un detalle importante del
especificación
es que la implementación puede informar falsos negativos (es decir, configurar isVisible
a false
, incluso cuando el elemento de destino sea completamente visible y no esté modificado)
Por cuestiones de rendimiento o por otros motivos, los navegadores se limitan a trabajar con límites.
cajas y geometría rectilínea; no tratan de lograr resultados de píxeles perfectos
modificaciones como border-radius
.
Dicho esto, no se permiten los falsos positivos en ninguna circunstancia (es decir, establecer
isVisible
a true
cuando el elemento de destino no es completamente visible ni no está modificado
¿Cómo se ve el nuevo código en la práctica?
El constructor IntersectionObserver
ahora toma dos propiedades de configuración adicionales: delay
.
y trackVisibility
.
delay
es un número que indica el retraso mínimo en milisegundos entre las notificaciones del
el observador de un objetivo determinado.
El trackVisibility
es un valor booleano que indica si el observador hará un seguimiento de los cambios en la capa de destino
visibilidad.
Es importante tener en cuenta que, cuando trackVisibility
es true
, delay
debe estar en
al menos 100
(es decir, no más de una notificación cada 100 ms)
Como se mencionó antes, el cálculo de la visibilidad es costoso, y este requisito es una precaución contra
la disminución del rendimiento y el consumo de la batería. El desarrollador responsable utilizará las
valor tolerable más alto para el retraso.
Según la actual spec, la visibilidad es calculada de la siguiente manera:
Si el atributo
trackVisibility
del observador esfalse
, el objetivo se considera visible. Esto se corresponde con el comportamiento de la versión 1 actual.Si el destino tiene una matriz de transformación eficaz que no sea una traducción 2D o un aumento proporcional en 2D, el objetivo se considera invisible.
Si el objetivo, o cualquier elemento de la cadena de bloques que lo contiene, tiene una opacidad efectiva distinta de 1.0, el objetivo se considera invisible.
Si al objetivo, o a cualquier elemento de la cadena de bloques que lo contiene, se aplicaron filtros, el objetivo se considera invisible.
Si la implementación no puede garantizar que otra página no oculte por completo el destino contenido, el objetivo se considera invisible.
Esto significa que las implementaciones actuales son bastante conservadoras y garantizan la visibilidad.
Por ejemplo, aplicar un filtro de escala de grises casi imperceptible, como filter: grayscale(0.01%)
o establecer una transparencia casi invisible con opacity: 0.99
representaría el elemento
invisibles.
A continuación, se ofrece una breve muestra de código que ilustra las nuevas funciones de la API. Puedes ver su seguimiento de clics la lógica en acción en la segunda sección de la demostración. (pero ahora, intenta "mirar" el video del cachorro). Asegúrate de activar el "modo truco" de nuevo a inmediatamente conviértase en un publicador sospechoso y vea cómo Intersection Observer v2 evita de clics no legítimos en el anuncio. Esta vez, Intersection Observer v2 está para ayudarte. 🎉
<!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 Intersection Observer v2, falling back 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'));
Vínculos relacionados
- Último borrador del editor del Especificación de Intersection Observer.
- Intersection Observer v2 está activado Estado de la plataforma Chrome.
- Error de Chromium v2 de Intersection Observer.
- Parpadeo Intención de implementar la publicación.
Agradecimientos
Agradecimientos a Simeon Vincent: Yoav Weiss y Mathias Bynens por revisar este artículo, así como también Stefan Zager para revisar e implementar la función en Chrome. Imagen hero de Sergey Semin en Unsplash.