// apis
¿Qué es ResizeObserver? El redimensionado a nivel de elemento, y el error de bucle que todos encuentran
El evento resize de window no dice nada sobre un elemento concreto. ResizeObserver sí. Qué informa, la diferencia entre content box y border box, y por qué aparece en tu consola «ResizeObserver loop completed with undelivered notifications».
El evento resize de window se dispara cuando cambia el viewport. Eso es todo lo que sabe. Un elemento puede cambiar de tamaño por un contenedor flex, por una barra lateral que se abre, por una fuente que termina de cargar o por un textarea que se arrastra, y window no se enterará jamás.
ResizeObserver es la API que vigila un elemento en lugar de la ventana.
Qué informa realmente
MDN lo formula con precisión: la interfaz «informa de los cambios en las dimensiones de la content box o la border box de un Element, o de la bounding box de un SVGElement».
Esas dos cajas no son lo mismo, y confundirlas es una fuente clásica de errores de unos pocos píxeles. La content box es donde va el contenido: la border box menos el padding y el borde. La border box envuelve juntos el contenido, el padding y el borde.
const observer = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width, height } = entry.contentRect;
entry.target.classList.toggle('is-narrow', width < 400);
}
});
observer.observe(document.querySelector('.card')); El callback recibe un array de entradas porque un mismo observador puede vigilar varios elementos y varios pueden cambiar en el mismo frame. Leer entry.contentRect da la content box; entry.borderBoxSize y entry.contentBoxSize dan las cajas como arrays de objetos de dimensiones.
El error que todos encuentran: «loop completed with undelivered notifications»
Tarde o temprano aparece en la consola, y merece entenderse en vez de silenciarse.
El problema del que protege es circular: tu callback cambia el tamaño de algo, ese cambio vuelve a disparar el observador, que cambia otra vez el tamaño. A su aire, la página nunca se estabilizaría.
// Boucle: le callback change la taille de ce qu il observe
const bad = new ResizeObserver(([entry]) => {
entry.target.style.height = entry.contentRect.height + 1 + 'px';
}); La respuesta de la especificación, en palabras de MDN, es que «los bucles infinitos por dependencias cíclicas se abordan procesando en cada iteración solo los elementos más profundos del DOM». Todo lo que no cumpla esa condición se aplaza al siguiente repintado, y se dispara un evento de error en window con un mensaje fijo:
ResizeObserver loop completed with undelivered notifications.
Aquí está la parte que más importa, y MDN la enuncia sin rodeos: «esto solo evita el bloqueo del navegador, no el bucle infinito en sí». El navegador se protege a sí mismo, no arregla tu código. El mensaje es un síntoma, y el bucle sigue ahí.
Quizá veas también ResizeObserver loop limit exceeded, una redacción antigua de Chrome para la misma familia de problema. Cadena distinta, lo mismo que corregir.
Cómo dejar de provocarlo
No escribas en el callback nada que cambie el tamaño de lo que observas. Alternar una clase que solo cambia un color no tiene riesgo. Fijar una altura a partir de una altura medida es el bucle de manual.
Observa el padre, estiliza el hijo. Como el algoritmo procesa primero los elementos más profundos del DOM, actuar hacia abajo y no hacia arriba te deja del lado correcto.
Aplaza la escritura. Envolver la mutación en requestAnimationFrame la saca de la pasada de observación. Considéralo un apaño: si la dependencia es realmente circular, la has pospuesto, no eliminado.
Cuándo no lo necesitas en absoluto
Si solo quieres estilizar un componente según su propia anchura, las container queries de CSS lo hacen en CSS, sin callback ni bucle del que preocuparse. Reserva ResizeObserver para cuando necesites el número en JavaScript: redibujar un canvas, componer un gráfico o recalcular algo que CSS no sabe expresar.
Y si lo que vigilas es la entrada de un elemento en el viewport y no un cambio de tamaño, ese es otro observador distinto: consulta la Intersection Observer API.
En resumen
ResizeObserver es la respuesta a nivel de elemento a un evento a nivel de ventana. Elige la caja correcta, nunca redimensiones desde el callback aquello que observas, y lee el error de bucle como una señal real y no como ruido de consola: el navegador solo evitó congelarse, no arregló el ciclo.