scroll()
Vincula la animación al scroll de un contenedor específico. Perfecto para progress bars y elementos que siguen el scroll completo de la página.
animation-timeline: scroll(root);
Scroll Timeline API permite crear animaciones fluidas basadas en el scroll del usuario, eliminando completamente la necesidad de JavaScript o librerías externas. Declara tus animaciones en CSS y déjalas sincronizar con el scroll automáticamente.
Vincula la animación al scroll de un contenedor específico. Perfecto para progress bars y elementos que siguen el scroll completo de la página.
animation-timeline: scroll(root);
Anima elementos cuando entran, están visibles o salen del viewport. Ideal para reveal effects y parallax de elementos individuales.
animation-timeline: view();
Define exactamente cuándo comienza y termina la animación. Control preciso sobre entry, cover, contain y exit.
animation-range: entry 0% cover 40%;
Aparece gradualmente con un movimiento suave desde abajo.
animation-timeline: view();
Crece desde el centro mientras aparece en pantalla.
transform: scale(0.8) → scale(1)
Rota suavemente mientras se revela.
transform: rotateY(-15deg)
Enfoca desde un estado borroso.
filter: blur(10px) → blur(0)
Entra deslizándose desde el lado derecho.
transform: translateX(100px)
Se revela usando clip-path para un efecto dramático.
clip-path: inset(0 100% 0 0)
Cada card usa animation-timeline: view() para vincular su animación
a su posición en el viewport. Cuando el elemento entra, la animación comienza;
cuando sale, puede revertirse o completarse.
#2448A6
color-mix()
#F5B841
Esta sección usa animation-timeline: view() combinado con
animation-range: entry 0% exit 100% para crear una transición
suave de color mientras scrolleas. Sin JavaScript, solo CSS puro.
Usando clip-path animado, las imágenes se revelan con diferentes efectos.
El uso de clip-path es GPU-acelerado y no causa layout shifts,
manteniendo un performance óptimo.
@keyframes reveal-left {
from { clip-path: inset(0 100% 0 0); }
to { clip-path: inset(0 0 0 0); }
}
Primera card de la galería horizontal
Segunda card con scroll suave
Tercera card del carrusel
Cuarta card animada
Quinta y última card
Esta galería usa overflow-x: auto con scroll-snap-type
para crear un carrusel nativo sin JavaScript. Las animaciones de entrada
están vinculadas con view() timeline.
.progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: var(--primary);
transform-origin: left;
/* Vincula al scroll del documento */
animation: grow-bar linear;
animation-timeline: scroll(root);
}
@keyframes grow-bar {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.card {
opacity: 0;
transform: translateY(50px);
/* Se anima al entrar al viewport */
animation: fade-in linear;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
@keyframes fade-in {
to {
opacity: 1;
transform: translateY(0);
}
}
.element {
animation: complex-animation linear;
animation-timeline: view();
/* Controla cuándo comienza y termina */
animation-range: entry 0% exit 100%;
/* Otras opciones:
- entry: cuando empieza a entrar
- cover: cuando está cubriendo el viewport
- contain: cuando está completamente visible
- exit: cuando empieza a salir
*/
}
@keyframes complex-animation {
0% { transform: scale(0.8); opacity: 0; }
50% { transform: scale(1.1); opacity: 1; }
100% { transform: scale(1); opacity: 1; }
}
.horizontal-container {
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
}
.gallery-item {
scroll-snap-align: center;
/* Anima al entrar al viewport horizontal */
animation: slide-in linear;
animation-timeline: view(inline);
animation-range: entry 0% cover 30%;
}
@keyframes slide-in {
from {
opacity: 0;
transform: translateX(-50px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
// JavaScript + GSAP ScrollTrigger
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
gsap.to(".element", {
opacity: 1,
y: 0,
scrollTrigger: {
trigger: ".element",
start: "top 80%",
end: "top 20%",
scrub: true,
markers: true
}
});
// ... más configuración
// ... más código
// ... más mantenimiento
/* CSS Puro */
.element {
opacity: 0;
transform: translateY(50px);
/* ¡Eso es todo! */
animation: fade-in linear;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
@keyframes fade-in {
to {
opacity: 1;
transform: translateY(0);
}
}
/* Sin librerías
Sin dependencies
Sin JavaScript
Performance perfecto */
Crea experiencias inmersivas con parallax, reveal effects y transiciones suaves que captan la atención sin sacrificar performance.
Muestra tus proyectos con animaciones elegantes que se revelan al scrollear, creando una narrativa visual profesional.
Narra historias con elementos que aparecen progresivamente, guiando al usuario a través del contenido de forma natural.
Presenta productos con efectos visuales impactantes que destacan características clave mientras el usuario explora.
Anima gráficos y datos que se revelan al entrar al viewport, haciendo la información más digerible y atractiva.
Mejora artículos largos con progress bars, imágenes que se revelan y efectos que mantienen el engagement del lector.
animation-range: entry 0% cover 30%;
Comienza cuando el elemento empieza a entrar y termina cuando ha cubierto el 30% del viewport.
animation-range: cover 0% exit 100%;
Comienza cuando empieza a cubrir y termina cuando ha salido completamente.
animation-range: entry 0% exit 100%;
Se ejecuta durante todo el tiempo que el elemento está en el viewport.
animation-range: contain 0% contain 100%;
Solo se anima cuando el elemento está completamente visible dentro del viewport.
animation-timeline
scroll() o view().
animation-timeline: scroll(root);
animation-timeline: view();
animation-range
animation-range: entry 0% exit 100%;
animation-range: cover 20% cover 80%;
scroll()
scroll(root)
scroll(nearest)
scroll(y)
view()
view()
view(block)
view(inline 20px)
timeline-scope
timeline-scope: --myTimeline;
Scroll Timeline es una mejora progresiva. Los navegadores que no lo soporten simplemente mostrarán el contenido sin animaciones, manteniendo la funcionalidad completa.
/* Fallback para navegadores sin soporte */
@supports not (animation-timeline: scroll()) {
.animated-element {
/* Versión estática o animación CSS tradicional */
opacity: 1;
transform: none;
}
}
/* Feature detection con JavaScript (opcional) */
if (CSS.supports('animation-timeline', 'scroll()')) {
// Navegador soporta Scroll Timeline
document.body.classList.add('supports-scroll-timeline');
}
Para navegadores sin soporte nativo, existe un polyfill oficial que puede agregar la funcionalidad mediante JavaScript:
<script src="https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js"></script>
Nota: El polyfill añade ~15KB pero permite usar la API en todos los navegadores. Es una mejora progresiva opcional.
Limítate a transform y opacity para animaciones super fluidas.
Evita animar width, height o top/left.
✅ transform, opacity, filter, clip-path
❌ width, height, margin, padding
will-change prepara el navegador, pero úsalo solo cuando sea necesario
y remuévelo cuando termine la animación.
will-change: transform, opacity;
contain: layout paint aísla el elemento y evita que las animaciones
afecten el resto del layout.
contain: layout paint;
Usa content-visibility: auto para que el navegador solo renderice
elementos cercanos al viewport.
content-visibility: auto;