| [ Web Proxy ] |
| Viewing: https://developer.mozilla.org/es/docs/Web/API/Intersection_Observer_API | [Back] [Original] |
Get to know MDN better
Esta pgina ha sido traducida del ingls por la comunidad. Aprende ms y nete a la comunidad de MDN Web Docs.
This feature is well established and works across many devices and browser versions. Its been available across browsers since marzo de 2019.
* Some parts of this feature may have varying levels of support.
La API Observador de Interseccin provee una va asncrona para observar cambios en la interseccin de un elemento con un elemento ancestro o con el viewport del documento de nivel superior.
Histricamente, detectar la visibilidad de un elemento, o la visibilidad relativa de dos elementos, uno respecto del otro, ha sido una tarea difcil para la cual las soluciones no han sido muy fiables y propensas a causar que el navegador y los sitios a los que el usuario accede lleguen a ser lentos. A medida que la web ha madurado, la necesidad para este tipo de informacin ha ido en aumento. La informacin sobre interseccin es necesaria por muchas razones, tales como:
Implementar la deteccin de intersecciones en el pasado implicaba manejadores de eventos y bucles llamando a mtodos como Element.getBoundingClientRect() para reunir la informacin necesaria para cada elemento afectado. Dado que todo este cdigo corre sobre el hilo principal, incluso uno de estos puede causar problemas de rendimiento. Cuando un sitio es cargado con estos tests, las cosas pueden ponerse muy feas.
Considere una pgina web que usa scroll infinito. Usa una librera de terceros para manejar los anuncios situados peridicamente en la pgina, que tiene grficos animados aqu y all, y usa una librera personalizada que muestra cajas de notificacin y similares. Cada uno de estos tiene sus propias rutinas de deteccin de intersecciones, todas corriendo en el hilo principal. El autor del sitio web puede no darse cuenta de que esto est pasando, ya que estn usando dos libreras de las que quizs conocen muy poco acerca de su funcionamiento interno. A medida que el usuario desplaza la pgina, estas rutinas de deteccin de intersecciones estn disparando cdigo constantemente durante el scroll, lo que resulta en una experiencia que deja al usuario frustrado con el navegador, el sitio web y su ordenador.
El API Intersection Observer deja al cdigo registrar una funcin callback que se ejecuta si un elemento que se desea monitorizar entra o sale de otro elemento (o del viewport), o cuando la cantidad por la que ambos elementos se intersecan cambia en una cantidad requerida. De esta manera, los sitios no necesitan hacer nada sobre el hilo principal para mirar este tipo de interseccin entre elementos, y el navegador est libre para optimizar la gestin de intersecciones como le parezca conveniente.
Una cosa que el API Intersection Observer no puede decirle es: el nmero exacto de pixels que se solapan o especficamente cuales son; sin embargo, cubre el caso de uso mucho ms comn de "Si se intersecan por algn lugar alrededor del N%, necesito hacer algo."
La API Intersection Observer le permite configurar una funcin callback que es llamada cuando alguna de las siguientes circunstancias ocurren:
Tpicamente, usted querr observar los cambios en las intersecciones con respecto al ancestro scrollable ms cercano al elemento, o, si el elemento no desciende de un ancestro scrollable, al viewport. Para observar la interseccin relativa al elemento root, especifique null;
Tanto si est usted usando el viewport o algn otro elemento como root, el API funciona de la misma manera, ejecutando una funcin callback que usted le proporciona cuando la visibilidad del elemento target cambia al cruzar en la cantidad de interseccin deseada con el elemento root.
El grado de interseccin entre el elemento target y su elemento root es el intersection ratio. Esto es una representacin del porcentaje del elemento target que es visible, indicado como un valor entre 0.0 y 1.0.
Cree el intersection observer llamando a su constructor y pasndole una funcin callback para que se ejecute cuando se cruce un umbral (threshold) en una u otra direccin:
let options = {
root: document.querySelector("#scrollArea"),
rootMargin: "0px",
threshold: 1.0,
};
let observer = new IntersectionObserver(callback, options);
Un umbral de 1.0 significa que cuando el 100% del elemento target est visible dentro del elemento especificado por la opcin root, la funcin callback es invocada.
El objeto options pasado al constructor IntersectionObserver() le deja controlar las circunstancias bajo las cuales la funcin callback es invocada. Tiene los siguientes campos:
rootEl elemento que es usado como viewport para comprobar la visibilidad de elemento target. Debe ser ancestro de target. Por defecto es el viewport del navegador si no se especifica o si es null.
rootMarginMargen alrededor del elemento root. Puede tener valores similares a los de CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). Los valores pueden ser porcentajes. Este conjunto de valores sirve para aumentar o encoger cada lado del cuadro delimitador del elemento root antes de calcular las intersecciones. Por defecto son todos cero.
thresholdEs un nmero o un array de nmeros que indican a que porcentaje de visibilidad del elemento target, la funcin callback del observer debera ser ejecutada. Si usted quiere que se detecte cuando la visibilidad pasa la marca del 50%, debera usar un valor de 0.5. Si quiere ejecutar la funcin callback cada vez que la visibilidad pase otro 25%, usted debera especificar el array [0, 0.25, 0.5, 0.75, 1]. El valor por defecto es 0 (lo que significa que tan pronto como un pxel sea visible, la funcin callback ser ejecutada). Un valor de 1.0 significa que el umbral no se considera pasado hasta que todos los pixels son visibles.
Una vez usted ha creado el observer, necesita darle un elemento target para observar:
var target = document.querySelector("#listItem");
observer.observe(target);
// el callback que indicamos al observador ser ejecutado ahora por primera vez
// espera hasta que le asignemos un target a nuestro observador (an si el target no est actualmente visible)
Cuando el elemento target encuentra un threshold especificado por el IntersectionObserver, la funcin callback es invocada. La funcin callback recibe una lista de objetos IntersectionObserverEntry y el observer:
var callback = function (entries, observer) {
entries.forEach((entry) => {
// Cada entry describe un cambio en la interseccin para
// un elemento observado
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
};
Asegrese de que su funcin callback se ejecute sobre el hilo principal. Debera operar tan rpidamente como sea posible; si alguna cosa necesita tiempo extra para ser realizada, use Window.requestIdleCallback().
Tambin, note que si especifica la opcin root, el elemento target debe ser un descendiente del elemento root.
Todas las reas consideradas por la API de Intersection Observer son rectngulos; los elementos que su forma es irregular se considera que estn ocupando el rectngulo ms pequeo que encierra todas las partes del elemento. De forma similar, si la porcin visible de un elemento no es un rectngulo, entonces el rectngulo de interseccin del elemento se interpreta como el rectngulo ms pequeo que contiene todas las partes visibles del elemento.
Es til entender un poco sobre cmo las diferentes propiedades proporcionadas por IntersectionObserverEntry describe una interseccin.
Antes de poder realizar un seguimiento de la interseccin de un elemento en un contenedor, necesitamos saber qu cul es contendor. Este contenedor se le conoce como intersection root, o root element. Este puede ser un elemento del documento, que es ascendiente del elemento observado, o null, que usar el viewport del documento como contenedor.
El rectngulo usado como los lmites de la interseccin del intersection root pueden ser ajustados configurando la opcin root margin, rootMargin, cuando creamos el IntersectionObserver. Los valores en rootMargin define los espacios aadidos a cada lado del cuadro delimitador que sirve de contenedor, creando los lmites definitivos del contenedor, o intersection root (los cules estn explicados en IntersectionObserverEntry.rootBounds cuando la funcin callback es ejecutada).
En lugar de reportar cada mnimo cambio indicando cmo de visible es el elemento que observamos, la Intersection Observer API usa umbrales. Cuando creamos un observable, puedes proporcionar uno o ms valores nmericos representando, en porcentaje, cun visible es el elemento observado. Entonces, la API reporta slo los cambios de visibilidad que cruza este umbral.
Por ejemplo, si te gustara ser informado cada vez que la visibilidad del elemento pasa, hacia delante o haca atrs, una marca de un 25%, entonces puedes especificar el array [0, 0.25, 0.5, 0.75, 1] como una lista de umbrales a la hora de crear el observable. Puedes saber incluso en qu direccin la visibilidad ha cambiado (esto es, saber si el elemento ha pasado a ser ms o menos visible) comprobando el valor de la propiedad isIntersecting disponible en el IntersectionObserverEntry que tienes disponible en la funcin callback cada vez que la visibilidad cambia. Si isIntersecting es true, el elemento se ha vuelto al menos tan visibile como el umbral que pas. Si es false, el elemento entonces ha dejado de ser tan visible como el umbral que sobrepas.
Para entender cmo funciona el concepto de umbral (threshold), pruebe a hacer scroll en el siguiente ejemplo. Cada caja coloreada muestra dentro de ella el porcentaje que tiene visible de cada una de las cuadro esquinas, de forma que podr ver cmo cambian los porcentajes conforme va haciendo scroll. Cada caja tiene diferentes valores configurado de umbrales.
IntersectionObserver.thresholds, siendo su valor el array [0.00, 0.01, 0.02, ..., 0.99, 1.00].<template id="boxTemplate">
<div class="sampleBox">
<div class="label topLeft"></div>
<div class="label topRight"></div>
<div class="label bottomLeft"></div>
<div class="label bottomRight"></div>
</div>
</template>
<main>
<div class="contents">
<div class="wrapper"></div>
</div>
</main>
.contents {
position: absolute;
width: 700px;
height: 1725px;
}
.wrapper {
position: relative;
top: 600px;
}
.sampleBox {
position: relative;
left: 175px;
width: 150px;
background-color: rgb(245, 170, 140);
border: 2px solid rgb(201, 126, 17);
padding: 4px;
margin-bottom: 6px;
}
#box1 {
height: 200px;
}
#box2 {
height: 75px;
}
#box3 {
height: 150px;
}
#box4 {
height: 100px;
}
.label {
font:
14px "Open Sans",
"Arial",
sans-serif;
position: absolute;
margin: 0;
background-color: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(0, 0, 0, 0.7);
width: 3em;
height: 18px;
padding: 2px;
text-align: center;
}
.topLeft {
left: 2px;
top: 2px;
}
.topRight {
right: 2px;
top: 2px;
}
.bottomLeft {
bottom: 2px;
left: 2px;
}
.bottomRight {
bottom: 2px;
right: 2px;
}
let observers = [];
startup();
function startup() {
let wrapper = document.querySelector(".wrapper");
// Options for the observers
let observerOptions = {
root: null,
rootMargin: "0px",
threshold: [],
};
// Un array con los umbrales para cada caje.
// El umbral de la primer caja se crea de forma programtica
// ya que hay demasiados puntos.
let thresholdSets = [
[],
[0.5],
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
[0, 0.25, 0.5, 0.75, 1.0],
];
for (let i = 0; i <= 1.0; i += 0.01) {
thresholdSets[0].push(i);
}
// Aadimos cada caja y creamos un observable para cada una
for (let i = 0; i < 4; i++) {
let template = document
.querySelector("#boxTemplate")
.content.cloneNode(true);
let boxID = "box" + (i + 1);
template.querySelector(".sampleBox").id = boxID;
wrapper.appendChild(document.importNode(template, true));
// Configuramos el observable para esta caja
observerOptions.threshold = thresholdSets[i];
observers[i] = new IntersectionObserver(
intersectionCallback,
observerOptions,
);
observers[i].observe(document.querySelector("#" + boxID));
}
// Scroll a la posicin inicial
document.scrollingElement.scrollTop =
wrapper.firstChild.getBoundingClientRect().top + window.scrollY;
document.scrollingElement.scrollLeft = 750;
}
function intersectionCallback(entries) {
entries.forEach(function (entry) {
let box = entry.target;
let visiblePct = Math.floor(entry.intersectionRatio * 100) + "%";
box.querySelector(".topLeft").innerHTML = visiblePct;
box.querySelector(".topRight").innerHTML = visiblePct;
box.querySelector(".bottomLeft").innerHTML = visiblePct;
box.querySelector(".bottomRight").innerHTML = visiblePct;
});
}
El navegador computa el rectngulo de interseccin final de la siguiente forma; la API hace todo esto por usted, pero puede ser til entender estos pasos para comprender mejor cuando ocurrirn exactamente las intersecciones.
getBoundingClientRect() en el target. Este es el rectangulo de interseccin mas grande que puede ser. Los pasos restantes removeran las porciones que no intersectan.overflow. Establecer overflow en cualquier valor que no sea visible provoca que ocurra el recorte.<iframe>), el rectngulo de interseccin se recorta al rea visible del contenedor de este contexto y continua hacia arriba a travs de los contenedores con el bloque contenedor del contexto. As que, si se alcanza el nivel superior de un <iframe>, el rectngulo de interseccin se recorta al viewport del marco (<iframe>), y luego el elemento padre del marco es el siguiente bloque que se recorre hacia la raz de la interseccin.document objetivo.Cuando la cantidad del elemento target que es visible dentro del elemento root cruza uno de los umbrales de visibilidad, el callback del objeto IntersectionObserver es ejecutado. El callback recibe como input un array de todos los objetos IntersectionObserverEntry, uno por cada umbral que haya sido cruzado, y una referencia al objeto IntersectionObserver mismo.
Cada entrada en la lista de umbrales es un objeto IntersectionObserverEntry que describe un umbral que ha sido cruzado; esto es, cada entrada describe qu porcin de un elemento dado se est intersectando con el elemento root, sea que el elemento se considere en interseccin o no, y la direccin en la cual ocurri la transicin.
El siguiente fragmento de cdigo muestra una devolucin de llamada que mantiene un contador de cuntas veces los elementos hacen la transicin desde no intersectar con la raz hasta intersectar al menos en un 75%. Para un valor umbral de 0.0 (predeterminado), la devolucin de llamada es lanzada aproximadamente cuando hay una transicin en el valor booleano de IntersectionObserverEntry.isIntersecting. El fragmento de cdigo primero verifica que la transicin sea positiva y luego determina si IntersectionObserverEntry.intersectionRatio es superior al 75%; en ese caso, incrementa el contador.
intersectionCallback(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
let elem = entry.target;
if (entry.intersectionRatio >= 0.75) {
intersectionCounter++;
}
}
});
}
IntersectionObserverLa interfaz principal para la API de Observador de Intersecciones. Proporciona mtodos para crear y gestionar un observador que puede vigilar cualquier nmero de elementos de destino para la misma configuracin de interseccin. Cada observador puede observar de manera asncrona los cambios en la interseccin entre uno o ms elementos de destino (target) y un elemento ancestro compartido o con el viewport de su Document de nivel superior. El ancestro o el viewport se denomina root.
IntersectionObserverEntryDescribe la interseccin entre el elemento de destino y su contenedor raz en un momento especfico de transicin. Los objetos de este tipo solo se pueden obtener de dos maneras: como entrada para al devolucin de llamada de tu IntersectionObserver, o llamando a IntersectionObserver.takeRecords().
Este ejemplo causa que el elemento que queremos observar cambia de color y transparencia conforme se va haciendo ms o menos visible. En la pgina Timing element visibility with the Intersection Observer API, puedes encontrar un ejemplo ms extenso que muestra cmo calcular cuanto tiempo que una serie de elementos, como anuncios, son visibles para el usuario y reaccionar a esa informacin guardando estadsticas.
El HTML para este ejemplo es muy simple, con un elemento primario que ser la caja que querremos observar (con la creativa ID de "box") y algo de contenido para dentro de la caja.
<div id="box">
<div class="vertical">Welcome to <strong>The Box!</strong></div>
</div>
El CSS del ejemplo no es muy importante para el propsito de este ejemplo: pinta el elemento y establece que los atributos background-color y border puedan participar en las CSS transitions, los cules usaremos para afectar los cambios al elemento conforme este es ms o menos visible.
#box {
background-color: rgba(40, 40, 190, 255);
border: 4px solid rgb(20, 20, 120);
transition:
background-color 1s,
border 1s;
width: 350px;
height: 350px;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.vertical {
color: white;
font: 32px "Arial";
}
.extra {
width: 350px;
height: 350px;
margin-top: 10px;
border: 4px solid rgb(20, 20, 120);
text-align: center;
padding: 20px;
}
Finalmente, vamos a mirar el cdigo JavaScript que usa la API Intersection Observer API para hacer que las cosas ocurran.
Primero, necesitamos preparar algunas variables e instalar el observador.
var numSteps = 20.0;
var boxElement;
var prevRatio = 0.0;
var increasingColor = "rgba(40, 40, 190, ratio)";
var decreasingColor = "rgba(190, 40, 40, ratio)";
// Set things up.
window.addEventListener(
"load",
function (event) {
boxElement = document.querySelector("#box");
createObserver();
},
false,
);
Las constantes y variables que establecimos aqu son:
numStepsUna constante que indica cuntos puntos de umbral queremos tener entre una proporcin de visibilidad de 0.0 y 1.0.
prevRatioEsta variable se utilizar para registrar cul era la proporcin de visibilidad la ltima vez que se cruz un umbral; esto nos permitir determinar si el elemento de destino se est volviendo ms o menos visible.
increasingColorUna cadena que define un color que aplicaremos al elemento de destino cuando la proporcin de visibilidad est aumentando. La palabra "ratio" en esta cadena ser reemplazada por la proporcin de visibilidad actual del objetivo, de modo que el elemento no solo cambie de color, sino que tambin se vuelva cada vez ms opaco a medida que se oculta menos.
decreasingColorDe manera similar, esta es una cadena que define un color que aplicaremos cuando la proporcin de visibilidad est disminuyendo.
Llamamos a Window.addEventListener() para comenzar a escuchar el evento load; una vez que la pgina haya terminado de cargarse, obtenemos una referencia al elemento con el ID "box" utilizando querySelector(), luego llamamos al mtodo createObserver() que crearemos en un momento para manejar la creacin e instalacin del observador de interseccin.
El mtodo createObserver() se llama una vez que la carga de la pgina se completa para manejar la creacin real del nuevo IntersectionObserver y comenzar el proceso de observacin del elemento de destino.
function createObserver() {
var observer;
var options = {
root: null,
rootMargin: "0px",
threshold: buildThresholdList(),
};
observer = new IntersectionObserver(handleIntersect, options);
observer.observe(boxElement);
}
Comenzamos configurando un objeto options que contiene los ajustes para el observador. Queremos observar los cambios en la visibilidad del elemento de destino en relacin con el viewport del documento, por lo que root es null. No necesitamos ningn margen, as que el desplazamiento del margen, rootMargin, se especifica como "0px". Esto hace que el observador vigile los cambios en la interseccin entre los lmites del elemento de destino y los del viewport, sin espacio adicional (o sustraccin) alguno.
La lista de puntos de umbral de proporcin de visibilidad, threshold, se construye mediante la funcin buildThresholdList(). En este ejemplo, la lista de umbrales se construye programticamente, ya que hay varios de ellos y se pretende que el nmero sea ajustable.
Una vez que options est listo, creamos el nuevo observador llamando al constructor IntersectionObserver(), especificando una funcin que se llamar cuando la interseccin cruce uno de nuestros umbrales, handleIntersect(), y nuestro conjunto de opciones. Luego, llamamos a observe() en el observador devuelto, pasndole el elemento de destino deseado (target).
Podramos optar por vigilar los cambios de interseccin de visibilidad con respecto al viewport en varios elementos llamando a observer.observe() para cada uno de esos elementos, si as lo deseamos.
La funcin buildThresholdList(), que construye la lista de umbrales, se ve as:
function buildThresholdList() {
var thresholds = [];
for (var i = 1.0; i <= numSteps; i++) {
var ratio = i / numSteps;
thresholds.push(ratio);
}
thresholds.push(0);
return thresholds;
}
Esto construye el arreglo de umbrales, cada uno de los cuales es una proporcin entre 0.0 y 1.0, al agregar el valor i/numSteps al arreglo thresholds para cada entero i entre 1 y numSteps. Tambin agrega el valor 0 para incluirlo. El resultado, dado el valor predeterminado de numSteps (20), es la siguiente lista de umbrales:
| # | Ratio | # | Ratio |
|---|---|---|---|
| 1 | 0.05 | 11 | 0.55 |
| 2 | 0.1 | 12 | 0.6 |
| 3 | 0.15 | 13 | 0.65 |
| 4 | 0.2 | 14 | 0.7 |
| 5 | 0.25 | 15 | 0.75 |
| 6 | 0.3 | 16 | 0.8 |
| 7 | 0.35 | 17 | 0.85 |
| 8 | 0.4 | 18 | 0.9 |
| 9 | 0.45 | 19 | 0.95 |
| 10 | 0.5 | 20 | 1.0 |
Podramos, por supuesto, codificar manualmente el arreglo de umbrales en nuestro cdigo, y a menudo es lo que terminaremos haciendo. Pero este ejemplo deja espacio para agregar controles de configuracin para ajustar la granularidad, por ejemplo.
Cuando el navegador detecta que el elemento de destino (en nuestro caso, el que tiene el ID "box") ha sido revelado u ocultado de tal manera que su proporcin de visibilidad cruza uno de los umbrales en nuestra lista, llama a nuestra funcin de manejo, handleIntersect():
function handleIntersect(entries, observer) {
entries.forEach(function (entry) {
if (entry.intersectionRatio > prevRatio) {
entry.target.style.backgroundColor = increasingColor.replace(
"ratio",
entry.intersectionRatio,
);
} else {
entry.target.style.backgroundColor = decreasingColor.replace(
"ratio",
entry.intersectionRatio,
);
}
prevRatio = entry.intersectionRatio;
});
}
Para cada IntersectionObserverEntry en la lista entries, verificamos si intersectionRatio del registro est aumentando; si es as, establecemos background-color del elemento de destino con la cadena increasingColor (recuerda, es "rgba(40, 40, 190, ratio)"), reemplazando la palabra "ratio" con el valor de intersectionRatio del registro. El resultado: no solo cambia el color, sino que tambin cambia la transparencia del elemento de destino; a medida que la proporcin de interseccin disminuye, el valor alfa del color de fondo tambin disminuye, lo que resulta en un elemento ms transparente.
De manera similar, si intersectionRatio est aumentando, usamos la cadena decreasingColor y reemplazamos la palabra "ratio" en esa cadena con el valor de intersectionRatio antes de establecer background-color del elemento de destino.
Finalmente, para rastrear si la proporcin de interseccin est aumentando o disminuyendo, recordamos la proporcin actual en la variable prevRatio.
Abajo se encuentra el contenido resultante. Desplace sta pgina hacia arriba y abajo y note como la apariencia de la caja cambia mientras lo hace.
Hay un ejemplo an ms extensivo en Cronometrando la visibilidad de un elemento con la API Intersection Observer.
| Specification |
|---|
| Intersection Observer # intersection-observer-interface |
IntersectionObserver y IntersectionObserverEntryThis page was last modified on 31 mar 2026 by MDN contributors.
Your blueprint for a better internet.
Portions of this content are 19982026 by individual mozilla.org contributors. Content available under a Creative Commons license.
| Web Proxy Viewer | New URL | Original Page |