Product Craft Bible
View Transitions
Inicio Avanzado View Transitions
Avanzado

View Transitions

6 reglas chrome developers · mdnchrome developers, mdnmdn, webaim, apple higchrome developers · nngroup
116

View Transitions

6 reglas
1040

Progressive enhancement obligatorio

La View Transitions API no esta disponible en todos los browsers. El código debe funcionar identicamente sin transiciones cuando la API no existe. El patrón correcto: envolver la navegación en if (document.startViewTransition) y usar la navegación nativa como fallback. Nunca requerir la API para que la navegación funcione, es una mejora, no un requisito.

chrome developers · mdn
Preferir
link.addEventListener('click', async (e) => {
  e.preventDefault();
  const updateDOM = () => navigate(link.href);

  if (document.startViewTransition) {
    document.startViewTransition(() => updateDOM());
  } else {
    updateDOM();
  }
});
Guarda explicita: navegación nativa en browsers sin soporte, transición animada donde esta disponible, progresivo por definición
Evitar
// Sin fallback
link.addEventListener('click', async (e) => {
  e.preventDefault();
  await document.startViewTransition(
    async () => navigate(link.href)
  );
  // Firefox: "startViewTransition is not a function"
});
Sin el if de guarda, en Firefox y Safari la navegación falla completamente, el usuario no puede cambiar de página
1041

Morph de elementos: view-transition-name

Asignar view-transition-name a un elemento en la vista de origen y el mismo nombre al elemento correspondiente en la vista de destino hace que el browser anime automáticamente la posición, tamaño y forma entre los dos estados. Es el efecto "hero transition" de iOS nativo en el web. El nombre debe ser único en el documento, dos elementos con el mismo nombre en la misma vista cancelan la transición.

chrome developers · mdn
Preferir
Con view-transition-name
Producto A
$2,400
Detalle (morph continuo)
view-transition-name: product-image;

::view-transition-old(product-image) {
  animation: fade-out 0.25s ease;
}
::view-transition-new(product-image) {
  animation: fade-in 0.25s ease;
}
Mismo view-transition-name en origen y destino: el browser anima posición, tamaño y forma automáticamente entre las dos vistas
Evitar
Sin view-transition-name
Producto A
$2,400
Detalle (corte brusco, sin morph)
Sin view-transition-name la transición es un fade genérico: la imagen y el título desaparecen y reaparecen en otra posición sin continuidad espacial
1042

Cross-document transitions opt-in

Las View Transitions entre documentos distintos (navegación MPA normal) requieren que ambas páginas declaren @view-transition { navigation: auto; } en su CSS. Basta con que una página lo omita para que la transición no ocurra. Añadir la declaración en el CSS global del layout garantiza cobertura completa. Verificar en Chrome 126+, no disponible en otros browsers aún.

chrome developers, mdn
Preferir
site.com/about
About
/* globals.css */
@view-transition {
  navigation: auto;
}

/* Todas las páginas tienen opt-in */
<meta name="view-transition" content="same-origin">
Transición suave entre páginas MPA, sin overhead de SPA
Evitar
site.com/about
Cargando...
About
Hard reload entre páginas, flash blanco, sin continuidad visual
1043

Reduced-motion: desactiva o simplifica

Con prefers-reduced-motion: reduce, la View Transition debe simplificarse a un fade instantaneo (100ms) o desactivarse por completo. No simplemente "reducir" la velocidad, algunos usuarios tienen vestibular disorders y cualquier movimiento puede causar malestar. La transición reducida no es un subconjunto del diseño animado: es un diseño alternativo con cero movimiento lateral o de escala.

mdn, webaim, apple hig
Preferir
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*) {
    animation-duration: 0s;
  }
  /* O simplificar a crossfade corto: */
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none !important;
    mix-blend-mode: normal;
  }
}
animation-duration: 0s desactiva toda animación de transición. El cambio de vista es instantaneo, sin riesgo de malestar vestibular
Evitar
/* Solo reduce la velocidad */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*) {
    animation-duration: 600ms;
    /* slide y scale siguen activos */
  }
}
Reducir la velocidad no elimina el movimiento, sigue causando malestar en usuarios con sensibilidad vestibular
1044

Cuando NO usar View Transitions

View Transitions no son apropiadas para todas las interacciones. Usarlas en form submissions, error states, tab switches dentro de la misma página o modal open/close hace que la interfaz se sienta lenta y teatral. La API toma un snapshot del DOM antes de animar, lo que agrega latencia a acciones que deberan sentirse instantaneas. Reservar View Transitions para navegación entre páginas, transiciones lista-a-detalle y cambios de layout significativos. Para micro-interacciones dentro de la misma vista, CSS transitions y animations son más rápidas y apropiadas.

chrome developers · nngroup
Preferir
Navegación página a página
Lista a detalle (hero transition)
Cambios de layout significativos
Form submissions, error states
Within-page tab switches, modal open/close
Matriz de decisión clara: View Transitions para navegación entre vistas, CSS transitions para micro-interacciones dentro de la misma página
Evitar
View Transitions en cada interacción
Form submissions - snapshot innecesario
Error states - debe sentirse inmediato
Tab switches (misma página) - usar CSS transitions
Modal open/close - usar CSS transitions
Sobrecargar la API con micro-interacciones agrega latencia de snapshot a acciones que deben sentirse instantaneas. La UI se siente lenta y teatral
1045

Performance: snapshot rápida, DOM pesado no

La View Transitions API toma un screenshot del estado actual del DOM antes de animar. Si el DOM tiene miles de nodos o animaciones CSS corriendo, el snapshot puede tardar 100-300ms y percibirse como freeze. Contener la transición a un subárbol específico con view-transition-name en solo el elemento que cambia (no la página entera) reduce el snapshot de cientos de milisegundos a menos de 15ms. Verificar con performance.mark que el snapshot ocurra en menos de 100ms.

chrome developers · mdn
Preferir
Targeted subtree transition
/* Solo el panel que cambia */
.content-panel {
  view-transition-name: panel;
}

document.startViewTransition(() => {
  updatePanel(newContent);
});
// snapshot solo del subtree
snapshot: 12ms
Aplicar view-transition-name solo al elemento que cambia limita el snapshot a un subtree pequeño, 12ms sin freeze perceptible
Evitar
Full-page transition (1000+ nodes)
document.startViewTransition(() => {
  navigate(href);
});
// snapshot captura TODO el DOM
snapshot: 340ms
Transición sobre página completa con 1000+ nodos, el snapshot congela el frame 340ms, el usuario percibe un freeze visible