overflow-anchor ya es Baseline: cómo evitar saltos de scroll sin romper CLS
webdevelopment 25 de septiembre de 2026 · Mintec

overflow-anchor ya es Baseline: cómo evitar saltos de scroll sin romper CLS

overflow-anchor ya funciona en los navegadores principales. Explicamos cómo depurar saltos de scroll, proteger la lectura y medir el resultado sin romper CLS.

overflow-anchor ya es Baseline: cómo evitar saltos de scroll sin romper CLS

Sí: overflow-anchor ya es una opción de producción para controlar el anclaje de scroll, pero no corrige CLS por sí solo. El navegador puede conservar el punto que el usuario está leyendo cuando cambia el contenido fuera del viewport. overflow-anchor: none sirve para excluir una zona que está interfiriendo con ese comportamiento. La corrección depende de saber qué nodo está anclando el navegador y qué parte de la página está cambiando.

En nuestro trabajo de auditoría vemos un patrón que confunde a los equipos: el CLS puede verse limpio mientras el lector pierde el párrafo que estaba leyendo. La causa no siempre es una imagen sin width y height. También ocurre cuando un componente se inserta, se reordena o cambia de posición después de que el usuario ya se desplazó.

MDN ahora etiqueta el módulo como Baseline 2026, recién disponible. Los navegadores principales ya lo soportan, así que la decisión ya no es si conviene probarlo. La pregunta útil es: ¿en qué parte del documento hay que intervenir?

Qué problema resuelve realmente

El CSS Scroll Anchoring Module define un nodo de anclaje para cada contenedor de scroll. Cuando cambia el contenido por encima de la zona visible, el navegador puede ajustar el offset de scroll para que el elemento que la persona está leyendo permanezca en el mismo lugar de la pantalla.

MDN confirma que el comportamiento está activo por defecto en los navegadores compatibles. auto es el valor inicial. none excluye un elemento o un contenedor de la selección del ancla.

.article {
  /* El navegador puede elegir un descendiente como ancla */
  overflow-anchor: auto;
}

.dynamic-island {
  /* Esta zona no debe competir por ser el ancla */
  overflow-anchor: none;
}

El error habitual es añadir overflow-anchor: none a todo el documento "por si acaso". Eso elimina una protección nativa y deja que regrese el problema que intentabas corregir.

Por qué CLS puede permanecer en verde

CLS mide desplazamientos inesperados del contenido visible. No mide completamente si la persona perdió su lugar. Google explica en su guía de CLS que los cambios dentro de los 500 ms posteriores a una interacción no se cuentan. También diferencia el CLS de laboratorio del CLS de campo: CrUX observa la vida completa de la página, mientras que una carga inicial de Lighthouse puede no mostrar los cambios posteriores.

Síntoma que ve el usuarioQué puede estar pasandoQué dice CLS
Salta un bloque al terminar el scrollEl nodo de anclaje cambió o el contenido se insertó fuera del viewportPuede no contar
El párrafo se mueve después de una respuesta JSONEl contenido se actualiza en un contenedor y el ancla deja de ser establePuede quedar fuera si fue post-input
Una imagen sin dimensiones empuja todoFalta espacio reservado antes de cargarSuele contar
Un cambio de position rompe el anclajeEl navegador desactiva el anclaje en esa zonaNo siempre coincide con el CLS reportado

Si el usuario dice "se me movió la lectura", no descartes el problema porque CLS esté en 0.08. Graba la sesión o usa el panel de Layout Shifts para encontrar el nodo afectado.

El patrón que cambia el diagnóstico

En el trabajo de auditoría, el patrón que más cambia nuestro diagnóstico aparece en páginas con filtros, tablas y tarjetas que se actualizan después del scroll. El CLS puede verse bajo y, aun así, la persona pierde la línea que estaba leyendo. No hace falta inventar un porcentaje para encontrar el problema: basta con reproducir el cambio y observar dónde termina el nodo de anclaje.

La primera hipótesis suele ser "faltan dimensiones". La tabla puede tener una altura calculada, pero el contenido se inserta dentro de un contenedor que se reordena al cambiar el estado. Si el nodo que el navegador puede elegir está dentro de una tarjeta animada, un cambio de tamaño puede suprimir el anclaje y dejar el offset de scroll donde estaba.

La secuencia para confirmar el diagnóstico es:

  1. Reservar la altura mínima del bloque que puede cambiar.
  2. Sacar la zona animada de la selección del ancla con overflow-anchor: none.
  3. Registrar la posición visual del párrafo antes y después de la actualización.
  4. Repetir la prueba con una conexión lenta y una ventana de móvil.

El segundo punto suele faltar. overflow-anchor no crea una reserva de espacio. Solo controla qué nodo puede usarse para compensar un cambio. Si el layout está mal dimensionado, desactivar el anclaje cambia el síntoma, no la causa.

Una tabla para decidir dónde usarlo

Después de comparar páginas con banners, cards animadas y filtros, este es el marco que usamos antes de tocar CSS:

Componente¿Cambia fuera del viewport?¿El usuario está leyendo cerca?Acción recomendada
Hero estáticoNoNoDejar auto
Card con imagen tardíaSí, arribaA vecesReservar espacio y dejar auto
Banner animado sobre la lecturaSíSíExcluir la zona con none
Filtro que reemplaza resultadosSíFrecuentementeSeparar el bloque y reservar altura
Panel con position: fixedNoNoRevisar stacking y scroll
Contenido insertado por JavaScriptSíVariableMedir el shift y corregir la causa primero

La decisión no debería ser global. Es una pregunta por componente. Un carrusel puede quedar arriba del viewport y no necesitar none; el mismo carrusel insertado entre dos párrafos puede ser un pésimo ancla.

Cómo depurarlo en el navegador

La guía de Google para depurar layout shifts recomienda usar la Layout Instability API. La API solo está disponible en navegadores Chromium, pero sigue siendo el punto de partida más útil para identificar los nodos que se movieron.

Este snippet registra el valor y los elementos afectados sin contar los cambios que siguen a una interacción reciente:

let cls = 0;

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (entry.hadRecentInput) continue;

    cls += entry.value;
    const sources = entry.sources
      ?.map(({ node, previousRect, currentRect }) => ({
        node: node?.id || node?.className || node?.tagName,
        previousRect,
        currentRect,
      }))
      .slice(0, 5);

    console.table({ value: entry.value, startTime: entry.startTime, sources });
  }
}).observe({ type: 'layout-shift', buffered: true });

No lo ejecutes en producción sin filtrar: el volumen de logs puede afectar la sesión. Úsalo en una build de diagnóstico o detrás de una bandera local.

El test que encuentra el nodo problemático

Reproduce el caso en una ventana con una altura parecida a la de un móvil. Desplázate hasta una línea concreta. Guarda la posición visual del párrafo. Inserta o cambia el bloque sospechoso. La variable importante no es scrollY; es la posición del texto en la pantalla.

const before = paragraph.getBoundingClientRect().top;
updateContent();

requestAnimationFrame(() => {
  const after = paragraph.getBoundingClientRect().top;
  console.log({ before, after, visualDelta: after - before });
});

Si visualDelta es cercano a cero, el scroll anclado está cumpliendo su trabajo. Si el número coincide con la altura del bloque insertado, el anclaje no está corrigiendo esa zona. Ahora tienes evidencia para decidir entre reservar espacio, excluir el ancla o rehacer el flujo del componente.

overflow-anchor: none no arregla CLS

La propiedad controla la estabilidad percibida durante cambios de contenido. No corrige imágenes sin dimensiones, fuentes que ocupan otra altura, iframes sin espacio reservado ni un contenedor que cambia de tamaño antes de que el usuario pueda leerlo.

Google distingue entre CLS de carga y CLS de campo. Los labs suelen capturar el bloque de carga; CrUX registra shifts a lo largo de la sesión. Un cambio al hacer scroll puede aparecer en el campo aunque Lighthouse no lo haya visto, y los cambios post-input tienen una ventana de gracia de 500 ms.

Por eso el orden correcto es:

  1. Encontrar el nodo que se mueve.
  2. Corregir dimensiones, espacio reservado o el flujo de layout.
  3. Medir el antes y después.
  4. Usar overflow-anchor: none solo para una zona que interfiere con la lectura.

Poner * { overflow-anchor: none; } al principio del proyecto parece una política de rendimiento. En la práctica elimina el comportamiento nativo que mantiene estable el contenido mientras se carga. No lo hagas.

Un patrón para Astro y Next.js

En Astro, el HTML se genera antes de que la página llegue al navegador. El componente que puede cambiar debería tener una altura conocida o un contenedor que no se reinserte encima de la lectura:

<article>
  <div class="article-copy">
    <slot />
  </div>

  <aside class="related-content" aria-label="Contenido relacionado">
    <slot name="related" />
  </aside>
</article>

<style>
  .related-content {
    min-height: 18rem;
    overflow-anchor: none;
  }
</style>

En Next.js, no anclaría un Server Component que se reemplaza completo después de una mutación. Mantendría el shell y cambiaría solo el contenido:

export function ResultsPanel({ children }: { children: React.ReactNode }) {
  return (
    <section className="results-panel">
      {children}
    </section>
  );
}
.results-panel {
  min-height: 24rem;
  contain: layout;
}

contain: layout puede acotar el reflow del panel, pero no reemplaza las dimensiones explícitas ni evita que un componente se monte dos veces. Úsalo junto con una estructura estable, no como un parche.

La decisión final: auto, none o corregir primero

SituaciónDecisión
El contenido cambia arriba y el lector sigue el textoDejar auto
El ancla seleccionada no representa la lecturanone solo en esa zona
El contenido no tiene dimensiones conocidasCorregir dimensiones primero
Ocurre un shift después de una interacciónAuditar la interacción; puede no contar en CLS
CLS está bajo pero la lectura saltaMedir con getBoundingClientRect()

Para conectar este diagnóstico con el resto de tu arquitectura, revisa nuestra guía de rendimiento cross-browser, el framework de presupuestos para medios sintéticos y la implementación de carga diferida de video y audio.

Scroll anchoring ya es Baseline. La noticia útil no es que la propiedad exista: el navegador nos da una pieza de infraestructura que antes tocaba replicar con scripts frágiles. Pero el mayor salto de calidad sigue estando en el HTML: una imagen con tamaño, un panel con altura mínima y un componente que no mueve el contenido que alguien está leyendo.

En la práctica, no activamos overflow-anchor como una feature. Diagnóstico primero, medición después. El código debería ser el último paso de una investigación, no el primer parche.

Fuentes

Preguntas Frecuentes

¿Qué hace overflow-anchor en CSS?

Permite excluir una zona del documento de la selección del nodo de anclaje del navegador. El scroll anchoring está activo por defecto; overflow-anchor: none desactiva esa protección solo en la zona que indicas.

¿Usar overflow-anchor mejora el CLS?

No siempre. Puede reducir saltos percibidos cuando aparece contenido fuera del viewport, pero CLS ignora los desplazamientos que ocurren dentro de los 500 ms posteriores a una interacción. La métrica y la experiencia de lectura no son la misma medida.

¿Cuándo debería usar overflow-anchor: none?

Úsalo cuando el anclaje automático elige un nodo que no representa lo que el usuario está leyendo, como un carrusel, un bloque animado o un panel con posición dinámica. No lo uses como una regla global para tapar un problema de layout.

Artículos Relacionados