Transiciones y animaciones
Transiciones
Una transición hace que el cambio entre dos estados de un elemento sea gradual en lugar de instantáneo. Se define en el estado inicial del elemento y se activa cuando una propiedad cambia de valor, típicamente por una pseudoclase como :hover o :focus.
.boton {
background-color: #84ba3f;
color: white;
padding: 0.6rem 1.4rem;
border-radius: 4px;
transition: background-color 0.2s ease;
}
.boton:hover {
background-color: #5a9e2f;
}
La propiedad abreviada transition acepta: propiedad, duración, función de temporización y retardo:
/* transition: propiedad duración timing retardo */
transition: background-color 0.3s ease 0s;
/* Varias propiedades separadas por coma */
transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
/* Todas las propiedades animables */
transition: all 0.3s ease;
Usar all es cómodo pero poco preciso: también animará cambios que no querías, y puede afectar al rendimiento. Es mejor listar solo las propiedades necesarias.
Funciones de temporización
La función de temporización controla el ritmo del cambio: si avanza a velocidad constante, arranca despacio y acelera, frena al final, etc.
transition: transform 0.3s linear; /* velocidad constante */
transition: transform 0.3s ease; /* arranca rápido, frena al final (defecto) */
transition: transform 0.3s ease-in; /* arranca lento, acelera */
transition: transform 0.3s ease-out; /* arranca rápido, frena */
transition: transform 0.3s ease-in-out; /* lento al inicio y al final */
Para curvas completamente personalizadas se usa cubic-bezier(x1, y1, x2, y2). Herramientas como cubic-bezier.com permiten diseñarlas visualmente.
/* Efecto de rebote suave */
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
steps(n) crea una transición escalonada, útil para animaciones de sprites:
transition: background-position 0.5s steps(4);
La propiedad transform
transform desplaza, escala, rota o inclina un elemento sin afectar al flujo del documento. Es la propiedad más usada en animaciones porque el navegador la procesa en la GPU, sin recalcular el layout:
/* Desplazar */
transform: translateX(20px);
transform: translateY(-10px);
transform: translate(20px, -10px);
/* Escalar (1 = tamaño original) */
transform: scale(1.05);
transform: scaleX(0.8);
/* Rotar */
transform: rotate(45deg);
transform: rotate(-0.25turn);
/* Inclinar */
transform: skewX(15deg);
/* Combinar transformaciones */
transform: translateY(-4px) scale(1.02);
Combinado con transiciones, transform produce los efectos más fluidos:
.tarjeta {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.tarjeta:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
Animaciones con @keyframes
Las animaciones van más allá de las transiciones: no dependen de un evento del usuario y pueden definir cualquier número de pasos intermedios. Se componen de dos partes: la definición de la secuencia con @keyframes y la aplicación al elemento con la propiedad animation.
/* 1. Definir la secuencia */
@keyframes aparecer {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 2. Aplicar al elemento */
.mensaje {
animation: aparecer 0.4s ease-out;
}
Se pueden definir tantos fotogramas intermedios como sean necesarios usando porcentajes:
@keyframes pulsar {
0% { transform: scale(1); }
50% { transform: scale(1.08); }
100% { transform: scale(1); }
}
@keyframes girar {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
Propiedades de animación
.icono-carga {
animation-name: girar;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: normal; /* normal | reverse | alternate | alternate-reverse */
animation-fill-mode: both; /* none | forwards | backwards | both */
animation-delay: 0s;
animation-play-state: running; /* running | paused */
}
La forma abreviada: animation: nombre duración timing retardo repeticiones dirección fill-mode:
.icono-carga { animation: girar 1s linear infinite; }
.alerta { animation: pulsar 2s ease-in-out 3 alternate; }
animation-fill-mode controla qué estilos aplica el elemento cuando la animación no está activa. forwards mantiene el estilo del último fotograma al terminar; backwards aplica el primer fotograma durante el retardo; both hace ambas cosas.
Qué propiedades animar
No todas las propiedades CSS se animan igual de bien. Cuando el navegador anima width, height, margin, padding o top/left, tiene que recalcular el layout de la página en cada fotograma, lo que puede producir saltos en dispositivos lentos.
Las propiedades que el navegador puede delegar a la GPU y animar sin recalcular el layout son solo dos:
transform(mover, escalar, rotar)opacity(transparencia)
En la práctica, la mayoría de efectos visuales se pueden conseguir con estas dos propiedades y las transiciones de color (background-color, color, border-color), que también son ligeras.
prefers-reduced-motion
Algunos usuarios configuran su sistema operativo para reducir el movimiento en pantalla, ya sea por preferencia, por fotosensibilidad o por problemas vestibulares que hacen que las animaciones les provoquen mareo. CSS expone esa preferencia con una media query:
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
Esta regla no elimina las animaciones por completo (lo que podría romper el layout en algunos casos) sino que las hace instantáneas. El !important está justificado aquí: es una preferencia de accesibilidad que debe ganar a cualquier otra regla.
Recapitulación
- Las transiciones suavizan el cambio entre dos estados. Se definen en el estado base y se activan cuando una propiedad cambia. La forma abreviada:
transition: propiedad duración timing. - Funciones de temporización:
ease(defecto),linear,ease-in,ease-out,ease-in-out,cubic-bezier(),steps(). transformdesplaza (translate), escala (scale), rota (rotate) e inclina (skew) sin afectar al flujo. Es la propiedad más eficiente para animar.- Las animaciones con
@keyframesdefinen secuencias de varios pasos y no dependen de eventos del usuario. - Propiedades clave de
animation:duration,timing-function,iteration-count,direction,fill-mode,delay. - Animar preferentemente
transformyopacity: son las únicas propiedades que el navegador delega a la GPU sin recalcular el layout. - Respetar siempre
prefers-reduced-motion: reducepara usuarios con sensibilidad al movimiento.
Tu proyecto
Añade transiciones a los elementos interactivos del portfolio. Todo en estilos.css:
/* Transición base en los enlaces de nav */
.nav-principal a {
transition: color 0.2s ease;
}
/* Las tarjetas suben ligeramente al pasar el cursor */
.tarjeta {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.tarjeta:hover {
transform: translateY(-4px);
box-shadow: var(--sombra);
}
/* El botón de envío del formulario */
.formulario-contacto button {
transition: background-color 0.2s ease, transform 0.1s ease;
}
.formulario-contacto button:hover {
background-color: var(--color-acento);
}
.formulario-contacto button:active {
transform: scale(0.97);
}
/* Respeta las preferencias del sistema */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
}
}
Las transiciones deben ser sutiles. 200ms es el tiempo estándar para interacciones de hover: suficientemente rápido para no parecer lento, suficientemente largo para que se perciba como un cambio suave.
En la próxima lección: media queries y diseño responsive: cómo hacer que el portfolio se vea bien en móvil, tablet y escritorio.