View Transitions
Transiciones animadas entre estados y entre páginas, con muy poco código.
El navegador captura el antes y el después y anima la diferencia. Tú decides qué elementos se emparejan (view-transition-name) y cómo se mueven, con pseudoelementos CSS. En una página basta envolver el cambio en document.startViewTransition().
Dentro de una página son Baseline desde octubre de 2025 (Firefox 144). Entre páginas de un mismo sitio basta @view-transition { navigation: auto; } en Chrome, Edge y Safari; en Firefox aún está en desarrollo. Esta web la usa al pasar de una ficha a otra.
Para qué sirve
- Listas que se reordenan o filtran con continuidad
- Del listado al detalle sin perder el hilo
- Webs de varias páginas que se sienten como una app
Demo
Cada cambio va dentro de document.startViewTransition(): el navegador anima la diferencia. Pulsa una muestra para abrirla. Y entre páginas: pasa a la ficha anterior o siguiente y fíjate en el título.
Muestra
Compatibilidad
Baseline · nueva · 14 oct 2025| Función | Escritorio | Móvil | |||||
|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Safari | Chrome Android | Firefox Android | Safari iOS | |
| En la misma página | 111Chrome: 111 | 111Edge: 111 | 144Firefox: 144 | 18Safari: 18 | 111Chrome: 111 | 144Firefox: 144 | 18Safari: 18 |
| Entre páginas (@view-transition) | 126Chrome: 126 | 126Edge: 126 | —1Firefox: No | 18.2Safari: 18.2 | 126Chrome: 126 | —Firefox: No | 18.2Safari: 18.2 |
| Limitadas a un elemento | 147Chrome: 147 | 147Edge: 147 | —Firefox: No | —Safari: No | 147Chrome: 147 | —Firefox: No | —Safari: No |
- 1En desarrollo; forma parte de Interop 2026.
Compatibilidad generada en cada publicación desde MDN browser-compat-data 8.1.3 (24 sep 2026) · web-features 3.40.0 · revisión manual: 1 oct 2026
Código mínimo
<!doctype html>
<meta charset="utf-8">
<title>View Transitions · ejemplo mínimo</title>
<style>
/* Entre páginas del mismo origen: basta con esta regla en las dos páginas */
@view-transition { navigation: auto; }
ul { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; padding: 0; }
li { width: 80px; height: 80px; display: grid; place-items: center; background: #c0643a; color: #fff; font: 600 24px system-ui; }
/* Cada elemento anima por su cuenta; la clase permite darles a todos la misma curva */
li { view-transition-name: match-element; view-transition-class: card; }
::view-transition-group(.card) { animation-duration: 0.4s; }
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none; }
}
</style>
<p><button id="shuffle">Barajar</button> · <a href="pagina-2.html">Ir a la página 2 (transición entre documentos)</a></p>
<ul id="list"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>
<script>
const list = document.querySelector('#list');
const shuffle = () => [...list.children].sort(() => Math.random() - 0.5).forEach((li) => list.append(li));
document.querySelector('#shuffle').onclick = () => {
// Sin soporte, el cambio se hace igual, sin animación
if (!document.startViewTransition) return shuffle();
document.startViewTransition(shuffle);
};
</script><!doctype html>
<meta charset="utf-8">
<title>View Transitions · ejemplo mínimo</title>
<style>
/* Entre páginas del mismo origen: basta con esta regla en las dos páginas */
@view-transition { navigation: auto; }
ul { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; padding: 0; }
li { width: 80px; height: 80px; display: grid; place-items: center; background: #c0643a; color: #fff; font: 600 24px system-ui; }
/* Cada elemento anima por su cuenta; la clase permite darles a todos la misma curva */
li { view-transition-name: match-element; view-transition-class: card; }
::view-transition-group(.card) { animation-duration: 0.4s; }
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none; }
}
</style>
<p><button id="shuffle">Barajar</button> · <a href="pagina-2.html">Ir a la página 2 (transición entre documentos)</a></p>
<ul id="list"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>
<script>
const list = document.querySelector('#list');
const shuffle = () => [...list.children].sort(() => Math.random() - 0.5).forEach((li) => list.append(li));
document.querySelector('#shuffle').onclick = () => {
// Sin soporte, el cambio se hace igual, sin animación
if (!document.startViewTransition) return shuffle();
document.startViewTransition(shuffle);
};
</script><!doctype html>
<meta charset="utf-8">
<title>View Transitions · página 2</title>
<style>
@view-transition { navigation: auto; }
h1 { font: 600 32px system-ui; }
</style>
<h1>Página 2</h1>
<p>Esta navegación ha usado una transición entre documentos (Chrome 126+, Safari 18.2+).</p>
<p><a href="index.html">Volver</a></p><!doctype html>
<meta charset="utf-8">
<title>View Transitions · página 2</title>
<style>
@view-transition { navigation: auto; }
h1 { font: 600 32px system-ui; }
</style>
<h1>Página 2</h1>
<p>Esta navegación ha usado una transición entre documentos (Chrome 126+, Safari 18.2+).</p>
<p><a href="index.html">Volver</a></p>Novedades
Ten en cuenta
- Entre páginas, las dos deben activarla y ser del mismo origen; una redirección a otro origen la cancela.
- match-element empareja por identidad y solo sirve dentro de un documento; entre páginas usa nombres únicos.
- Respeta prefers-reduced-motion y comprueba que startViewTransition existe antes de usarlo.
Más información
Fuentes
- Chrome · Element-scoped view transitions27 mar 2026
- Interop 202612 feb 2026
- Bugzilla 1860854 (Firefox, entre documentos)consultado el 1 oct 2026
- web-features · view-transitions30 sep 2026