Consigna y contexto
Un producto busca transiciones coherentes entre vistas de lista, detalle y filtrado sin sacrificar la navegación nativa, la accesibilidad ni el rendimiento en dispositivos de gama baja. Diseña un plan de mejora progresiva: utiliza document.startViewTransition() para actualizaciones en el mismo documento, declaraciones CSS para navegación entre documentos, y explica el comportamiento cuando la API no está disponible, falla una actualización del DOM o el usuario prefiere movimiento reducido.
Esto encaja en roles de frontend, sistemas de diseño y rendimiento. MDN, Chrome for Developers y la especificación de CSS View Transitions definen el ciclo de vida de ViewTransition, los mecanismos en el mismo documento y entre documentos, el árbol de animación de pseudoelementos y el comportamiento de omisión. Este artículo se deriva de estándares públicos, no de una afirmación sobre el banco de entrevistas de una empresa.
Qué evalúa el entrevistador
El entrevistador está evaluando si separas la semántica de navegación, las actualizaciones del DOM, el ciclo de vida de la animación y los límites de respaldo. Una respuesta sólida menciona ready, updateCallbackDone, finished, skipTransition(), prefers-reduced-motion, valores únicos de view-transition-name y límites de mismo origen. Una respuesta débil añade una regla CSS de desvanecimiento sin un plan ante fallas.
Preguntas para clarificar
- ¿El objetivo es un cambio de estado en una SPA, navegación entre documentos o ambos?
- ¿Qué elementos necesitan identidad compartida y las tarjetas de lista tienen IDs estables al abrir los detalles?
- ¿La navegación central y la indexación deben funcionar sin JavaScript?
- ¿Qué duración de animación, presupuesto para dispositivos de gama baja y requisitos de movimiento reducido tiene el producto?
Una respuesta en 30 segundos
“Mantendría la navegación nativa y las actualizaciones de estado como la fuente de la verdad y usaría View Transitions como mejora progresiva. Para una SPA, envuelve una actualización sincrónica o asincrónica del DOM en startViewTransition(update) y anima los pseudoelementos después de ready; para navegación entre páginas múltiples, usa @view-transition { navigation: auto; } del mismo origen con nombres estables para elementos compartidos. Si la API falta, la actualización falla o se solicita movimiento reducido, completa la actualización sin animación y llama a skipTransition() cuando sea necesario. Los nombres únicos, los tiempos de espera y las métricas evitan que las transiciones bloqueen el comportamiento del producto.”
Solución paso a paso
Para una transición en el mismo documento, llama a document.startViewTransition(() => update()). El navegador captura el estado anterior, ejecuta el callback de actualización y crea el nuevo estado; el ViewTransition devuelto expone las promesas ready, updateCallbackDone y finished. Si el callback arroja un error, la aplicación sigue siendo responsable del manejo de errores; el envío comercial no debe depender del éxito de la animación. Personaliza la transición con pseudoelementos como ::view-transition-old(root) y ::view-transition-new(root).
Usa view-transition-name para emparejar un elemento antiguo con su contraparte nueva. Los nombres deben ser únicos en un árbol de transición. Las listas necesitan IDs de negocio estables en lugar de índices de arreglo; de lo contrario, ordenar o filtrar emparejará los elementos incorrectos. Nombra solo los elementos importantes; demasiadas capturas y superficies del compositor aumentan el costo.
Las transiciones entre documentos dependen de la navegación en el mismo origen y de la declaración CSS @view-transition; JavaScript no llama a startViewTransition() para la navegación. Esto funciona para aplicaciones de páginas múltiples, pero depende de la compatibilidad del navegador, la política del mismo origen y el CSS de la página. Un enlace aún debe navegar normalmente sin una transición; una promesa de animación no debe bloquear la respuesta del servidor ni el comportamiento predeterminado del enlace.
El manejo del ciclo de vida necesita rutas de tiempo de espera y omisión. Si ready no se resuelve dentro de un presupuesto, registra la razón y llama a skipTransition(). La navegación hacia atrás, el envío de formularios y salir de la página deben priorizar la navegación. Usa finished solo para limpieza y métricas, nunca como prueba de que los datos se guardaron. Para datos asincrónicos, define el límite de confirmación del estado antes de decidir si esperar la transición.
La accesibilidad implica respetar @media (prefers-reduced-motion: reduce) estableciendo la duración de la animación en cero u omitiéndola. Preserva el foco, los encabezados y el orden de lectura; la posición visual no puede reemplazar las actualizaciones semánticas. Los usuarios de teclado, lectores de pantalla y dispositivos lentos deben recibir el mismo resultado de contenido.
La mejora progresiva combina la detección de capacidades con un respaldo de navegación real. Si document.startViewTransition está ausente, llama a la función de actualización directamente; si no hay compatibilidad entre documentos, mantén los enlaces comunes. Mide la tasa de compatibilidad, la tasa de omisión, la latencia de ready, la tasa de fotogramas y la latencia de interacción por navegador y dispositivo. Una transición puede cambiar la presentación, pero nunca la corrección de la caché, los permisos, el envío de formularios o el enrutamiento.
Respuesta modelo
Mantendría la navegación y el envío de estados independientes de la animación. Una SPA utiliza startViewTransition(update) y anima solo los elementos compartidos esenciales después de ready; una aplicación de páginas múltiples utiliza @view-transition del mismo origen. Cada elemento compartido recibe un nombre de negocio único y estable, y una actualización asincrónica fallida omite la transición mientras muestra el estado de error normal.
Los navegadores no compatibles utilizan actualizaciones o enlaces nativos. Los usuarios con movimiento reducido obtienen ninguna animación o una acortada. Los tiempos de espera del ciclo de vida conservan skipTransition(). El foco, los encabezados y el orden semántico nunca dependen del efecto visual. Monitorea la compatibilidad, las omisiones y la latencia de interacción, y luego expande el conjunto de elementos con nombre tras un despliegue canary.
Errores comunes
- Error → usar un índice de arreglo como
view-transition-name; Por qué falla → ordenar empareja los nodos antiguos y nuevos incorrectos; Solución → usar un ID de negocio estable y garantizar la unicidad. - Error → esperar a
finishedantes de enviar un formulario; Por qué falla → una falla en la animación bloquea la acción de negocio; Solución → confirmar el estado primero y animar solo la presentación. - Error → diseñar solo la ruta de SPA; Por qué falla → la navegación entre páginas múltiples no tiene un punto de llamada en JavaScript; Solución → usar
@view-transitiondel mismo origen y conservar los enlaces ordinarios. - Error → ignorar las preferencias de movimiento reducido; Por qué falla → los usuarios sensibles pueden experimentar mareos o carga cognitiva; Solución → acortar u omitir la animación en la media query.
Preguntas de seguimiento
¿Cómo debería afectar un callback de actualización fallido a la transición y al estado?
Trata el callback de actualización como el límite del estado de negocio: captura la excepción, revierte o renderiza un error y mantén la promesa de la transición limitada al ciclo de vida de la animación. Si updateCallbackDone se rechaza, llama a skipTransition() o deja que el navegador termine la presentación predeterminada; no silencies el error.
¿Por qué no nombrar cada elemento como un elemento compartido?
Cada nombre debe formar un par sin ambigüedades entre los árboles antiguo y nuevo. Nombrar todo aumenta el costo de captura, diseño (layout) y composición, y puede generar coincidencias accidentales. Nombra solo los objetos clave que los usuarios comprendan; usa un desvanecimiento raíz o ninguna animación para el resto.
¿Cómo demuestras que la transición no perjudica el rendimiento?
Mide la latencia de ready, la tasa de fotogramas, las tareas largas (long tasks), la latencia de la primera interacción (first-input latency) y la tasa de omisiones por navegador y dispositivo, luego prueba con tamaños de lista realistas. Si los dispositivos de gama baja muestran una pérdida sostenida de fotogramas, reduce el alcance de la animación u omítela automáticamente manteniendo inalterado el tiempo de navegación.