El mapa real del soporte en 2026
Qué motor implementa qué, por qué Firefox no ha enviado las timelines de scroll, y qué se ve exactamente en un navegador que no las tiene.
Los dos niveles anteriores han enseñado un sistema completo y coherente que no funciona en uno de los tres motores de navegador. Ese hecho no es una nota al pie ni un problema que se resuelve al final con un parche: condiciona cómo se escriben los keyframes, dónde va el estado inicial y qué se puede prometer al diseño. Este nivel entero es sobre eso, y empieza por establecer con precisión qué hay y qué no, porque la mitad de los artículos que encontrarás en la web se equivocan al respecto.
- Enumerar el estado exacto de soporte por motor y por versión.
- Distinguir “implementado tras un flag” de “disponible para el público”.
- Describir qué ve un usuario de Firefox ante cada uno de los patrones de los niveles 15 y 16.
- Clasificar un efecto por su modo de fallo antes de decidir si se adopta.
Quién tiene qué
| Motor | Estado | Desde |
|---|---|---|
| Chromium (Chrome, Edge, Opera, Samsung Internet) | Implementado | 115 |
| WebKit (Safari, todos los navegadores de iOS) | Implementado | Safari 26 |
| Gecko (Firefox) | No implementado, solo tras flag | — |
Chromium fue el primero, en julio de 2023, con el conjunto completo: animation-timeline, scroll(), view(), las propiedades nombradas, animation-range y timeline-scope. Safari lo envió en la versión 26, en septiembre de 2025, y con eso el sistema pasó a estar disponible en dos de los tres motores y en la práctica totalidad de los dispositivos móviles, porque en iOS todos los navegadores usan WebKit.
Firefox no lo ha enviado. Existe una implementación parcial detrás del flag layout.css.scroll-driven-animations.enabled en about:config, activa en las builds de Nightly, y hay seguimiento público del trabajo restante. Pero no está activo para los usuarios, y “está en Nightly tras un flag” es, a efectos de lo que puedes construir, indistinguible de “no existe”. La documentación de referencia lo etiqueta como disponibilidad limitada: no forma parte de Baseline porque no funciona en uno de los navegadores más usados.
Hay una segunda erosión que conviene conocer porque afecta a código ya escrito: el valor timeline-scope: all existió en Chromium desde la 116 y fue retirado en la 138. Si mantienes un proyecto de 2023 o 2024 con animaciones de scroll, es un candidato a haberse roto sin que nadie lo relacione con una actualización del navegador.
Este es un tema donde la desinformación es sistemática, y por un motivo concreto: mucha documentación derivada confunde “existe tras un flag” con “está soportado”. Encontrarás artículos que afirman que Firefox 132 soporta animaciones dirigidas por scroll. Lo que Firefox 132 tiene es la preferencia en about:config, que es exactamente lo que documenta la página de características experimentales de Mozilla. La comprobación fiable no es un blog ni una tabla agregada: es abrir la página de la propiedad en la documentación de referencia y mirar la etiqueta de Baseline y la tabla de compatibilidad. Si dice disponibilidad limitada, no puedes contar con ello.
Por qué no está en Firefox
No es desidia ni falta de interés: la implementación es genuinamente difícil, y entender por qué ayuda a calibrar cuándo llegará.
El problema de fondo es que una animación dirigida por scroll rompe la separación entre el hilo principal y el hilo del compositor de una forma que las animaciones de tiempo no rompen. Una animación de tiempo se puede enviar entera al compositor: el compositor conoce el reloj, conoce los keyframes, y puede interpolar sin preguntar nada. Una animación de scroll depende de una posición que puede cambiar por scroll del usuario —que el compositor sí conoce— pero también por cambios de layout, por redimensionados y por scroll programático, que el compositor no conoce.
A eso se suma el problema de los bucles de realimentación que ya vimos: el progreso depende del layout y el layout puede depender del progreso. La especificación lo resuelve con un punto fijo del bucle de eventos y una ronda adicional de estilo y layout por frame, y encajar eso en un motor cuya arquitectura de composición se diseñó con otras premisas es trabajo de meses.
La consecuencia útil para ti no es una fecha, que nadie puede dar, sino una postura: planifica con la limitación, no contra ella. Un proyecto que necesite las animaciones de scroll para funcionar está mal planteado hoy. Un proyecto que las use como mejora está bien planteado y mejorará solo el día que Gecko las envíe, sin tocar una línea.
Qué se ve exactamente
Ser concreto sobre el modo de fallo es lo que permite decidir. En un motor sin timelines de scroll, animation-timeline: scroll() es una declaración con un valor que el motor no entiende, así que se descarta. Lo mismo con animation-range. Lo que queda en pie es el resto de la regla, y ahí está todo el problema.
| Patrón | Qué queda | Modo de fallo |
|---|---|---|
Barra de progreso con scaleX |
Barra completa, fija | Miente: dice que has leído todo |
Barra con display: none fuera del @supports |
Nada | Cosmético, correcto |
Revelado con opacity: 0 en la regla base |
Contenido invisible | Roto |
| Revelado con el estado final en la regla base | Contenido visible sin animación | Cosmético, correcto |
Paralaje sobre una imagen con translateY inicial |
Imagen descolocada | Degradado o roto según el recorte |
| Sombra de borde en un panel | Sin sombra | Cosmético, correcto |
| Cabecera que se compacta | Cabecera siempre alta | Cosmético, correcto |
La tabla enseña la lección entera: no hay un modo de fallo de las animaciones de scroll, hay tantos como formas de escribirlas, y la diferencia entre “cosmético” y “roto” está siempre en dónde has puesto el estado inicial. Si el estado inicial vive en la regla base, el fallo es roto. Si vive dentro del @keyframes y la regla base describe el estado final, el fallo es cosmético.
Ese es el principio que organiza todo el nivel, y la lección el estado final por defecto lo desarrolla como estrategia sistemática.
Vale la pena hacer bien la cuenta y luego resistirse a la conclusión fácil. Chromium y WebKit cubren, en la mayoría de mercados occidentales, la inmensa mayoría del tráfico web, y en móvil la cobertura es casi total porque en iOS todos los navegadores son WebKit por debajo. Alguien podría concluir de ahí que la limitación es marginal. Es un razonamiento que conviene desarmar por tres motivos independientes. Primero, la distribución no es uniforme: hay mercados y hay sectores —administración pública, universidades, entornos corporativos con navegador impuesto— donde la cuota de Firefox multiplica varias veces la media. Un porcentaje agregado es una media de poblaciones muy distintas y no te dice nada sobre la tuya. Segundo, el usuario de Firefox no es un usuario cualquiera: es, estadísticamente, alguien que ha tomado una decisión deliberada sobre su navegador, lo que correlaciona con perfiles técnicos, con preocupación por la privacidad y con la disposición a contarle a los demás que tu sitio está roto. Tercero, y es el argumento que zanja el asunto: el coste de hacerlo bien es ridículo. Escribir el estado final en la regla base y meter la animación en un @supports son dos líneas más y cero mantenimiento adicional. Cuando el coste de la mejora progresiva es dos líneas, discutir el porcentaje de cobertura es tiempo perdido: se hace y ya está. El debate sobre cuotas de mercado solo tiene sentido cuando el fallback es caro, y aquí no lo es.