Apuntes sobre Html2

Cuando uno enseña, dos aprenden.

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().
  • transform desplaza (translate), escala (scale), rota (rotate) e inclina (skew) sin afectar al flujo. Es la propiedad más eficiente para animar.
  • Las animaciones con @keyframes definen 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 transform y opacity: son las únicas propiedades que el navegador delega a la GPU sin recalcular el layout.
  • Respetar siempre prefers-reduced-motion: reduce para 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.

TOP