16. View transitions

Versión para imprimir.

A. Single page applications 1

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5
6 <meta charset="UTF-8">
7 <meta name="viewport"
8 content="width=device-width">
9 <title>
10 Single Page Application 1
11 </title>
12
13 <style>
14 nav {
15 display: flex;
16 align-items: center;
17 flex-wrap: wrap;
18 align-content: center;
19 list-style-type: none;
20 gap: 0.5rem;
21 }
22
23 @keyframes aparece {
24
25 /* La animación parte de
26 * opacidad 0 y automáticamente
27 * llega al default que es 1. */
28 from {
29 opacity: 0;
30 }
31 }
32
33 @keyframes desvanece {
34
35 /* La animación parte
36 * automáticamente del default
37 * de opacidad que es 1 y llega
38 * a 0. */
39 to {
40 opacity: 0;
41 }
42 }
43
44 /* Al terminar una vista, corre
45 * una animación sobre el
46 * elemento con
47 * view-transition-name: root,
48 * que por default es el tipo
49 * html. */
50 ::view-transition-old(root) {
51 animation-name: desvanece;
52 animation-duration: 1s;
53 }
54
55 /* Al iniciar la transición a
56 * una vista nueva, corre una
57 * animación sobre el elemento
58 * con
59 * view-transition-name: root,
60 * que por default es el tipo
61 * html. */
62 ::view-transition-new(root) {
63 animation-name: aparece;
64 /* Espera 1s antes de iniciar la
65 * animación, para permitir que
66 * la vista anterior se
67 * desvanezca. */
68 animation-delay: 1s;
69 animation-duration: 2s;
70 }
71 </style>
72
73</head>
74
75<body>
76
77 <nav>
78 <a href="inicio">Inicio</a>
79 <a href="acercade">Acerca de</a>
80 <a href="contacto">Contacto</a>
81 </nav>
82
83 <main id="inicio">
84 <h1>
85 Single Page Application 1
86 </h1>
87 <p>
88 Esta es la página principal.
89 </p>
90 </main>
91
92 <main id="acercade" hidden>
93 <h1>Acerca de</h1>
94 <p>
95 Esta es la página Acerca de.
96 </p>
97 </main>
98
99 <main id="contacto" hidden>
100 <h1>Contacto</h1>
101 <p>
102 Esta es la página Contacto.
103 </p>
104 </main>
105
106 <footer>
107 <p>
108 © 2025
109 Gilberto Pacheco Gallegos.
110 </p>
111 </footer>
112
113 <script>
114
115 // https://www.w3.org/TR/css-view-transitions-1/
116 const titulos = new Map([
117 [
118 "inicio",
119 "Single Page Application 1"
120 ],
121 [
122 "acercade",
123 "Acerca de - Single Page Application 1"
124 ],
125 [
126 "contacto",
127 "Contacto - Single Page Application 1"
128 ],
129 ])
130
131 const vistas =
132 [inicio, acercade, contacto]
133
134 /* Al cliquear detecta si es
135 * sobre un enlace y en este caso
136 * evita el salto a otra página
137 * y muestra la vista
138 * seleccionada.
139 */
140 document.addEventListener(
141 "click",
142 event => {
143 event.preventDefault()
144 const target = event.target
145 if (
146 target instanceof HTMLAnchorElement
147 ) {
148 try {
149 const href = target.href
150 /* Se queda con el nombre de
151 * la vista. */
152 const estado =
153 href.substring(
154 href.lastIndexOf("/") + 1
155 )
156 transicion(estado)
157 /* Agrega una nueva posición
158 * en la historia del
159 * navegador, simulando una
160 * nueva página, usando el
161 * valor de estado para
162 * actualizar correctamente
163 * la página. */
164 history.pushState(
165 estado, "", location.href
166 )
167 } catch (err) {
168 console.error(err)
169 }
170 }
171 }
172 )
173
174 /* Maneja los botones de avanzar
175 * o retroceder en la historia,
176 * recuperando el estado para
177 * actualizar la página. */
178 window.addEventListener(
179 "popstate",
180 event => {
181 if (
182 typeof event.state === "string"
183 ) {
184 transicion(event.state)
185 }
186 }
187 )
188
189 history.replaceState(
190 "inicio", "", location.href
191 )
192
193 /**
194 * @param {string} estado
195 */
196 function muestraVista(estado) {
197 document.title =
198 titulos.get(estado) ?? ""
199 for (const vista of vistas) {
200 vista.hidden =
201 estado !== vista.id
202 }
203 }
204
205 /**
206 * Si el navegador tiene soporte
207 * para view tansitions, realiza
208 * la transición; de lo
209 * contrario, solo hace el cambio
210 * de vista.
211 * @param {string} estado
212 */
213 function transicion(estado) {
214 if (
215 typeof document.startViewTransition === "function"
216 ) {
217 document.startViewTransition(
218 () => muestraVista(estado)
219 )
220 } else {
221 muestraVista(estado)
222 }
223 }
224
225 </script>
226
227</body>
228
229</html>

B. Single page applications 2

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5
6 <meta charset="UTF-8">
7 <meta name="viewport"
8 content="width=device-width">
9 <title>
10 Single Page Application 2
11 </title>
12
13 <style>
14 nav {
15 display: flex;
16 align-items: center;
17 flex-wrap: wrap;
18 align-content: center;
19 list-style-type: none;
20 gap: 0.5rem;
21 }
22
23 main {
24 /* Los elementos tppo main
25 * llevan una transición con
26 * nombre main. */
27 view-transition-name: main;
28 }
29
30 @keyframes desplazaALaDerecha {
31 from {
32 transform: translateX(100vw);
33 }
34 }
35
36 @keyframes desplazaALaIzquierda {
37 to {
38 transform: translateX(-100vw);
39 }
40 }
41
42 ::view-transition-old(main) {
43 animation-name:
44 desplazaALaIzquierda;
45 animation-duration: 2s;
46 }
47
48 ::view-transition-new(main) {
49 animation-name:
50 desplazaALaDerecha;
51 animation-duration: 2s;
52 }
53 </style>
54
55</head>
56
57<body>
58
59 <nav>
60 <a href="inicio">Inicio</a>
61 <a href="acercade">Acerca de</a>
62 <a href="contacto">Contacto</a>
63 </nav>
64
65 <main id="inicio">
66 <h1>
67 Single Page Application 2
68 </h1>
69 <p>
70 Esta es la página principal.
71 </p>
72 </main>
73
74 <main id="acercade" hidden>
75 <h1>Acerca de</h1>
76 <p>
77 Esta es la página Acerca de.
78 </p>
79 </main>
80
81 <main id="contacto" hidden>
82 <h1>Contacto</h1>
83 <p>
84 Esta es la página Contacto.
85 </p>
86 </main>
87
88 <footer>
89 <p>
90 © 2025
91 Gilberto Pacheco Gallegos.
92 </p>
93 </footer>
94
95 <script>
96
97 const titulos = new Map([
98 [
99 "inicio",
100 "Single Page Application 2"
101 ],
102 [
103 "acercade",
104 "Acerca de - Single Page Application 2"
105 ],
106 [
107 "contacto",
108 "Contacto - Single Page Application 2"
109 ],
110 ])
111
112 const vistas =
113 [inicio, acercade, contacto]
114
115 document.addEventListener("click",
116 event => {
117 event.preventDefault()
118 const target = event.target
119 if (
120 target instanceof HTMLAnchorElement
121 ) {
122 try {
123 const href = target.href
124 const estado =
125 href.substring(
126 href.lastIndexOf("/") + 1
127 )
128 transicion(estado)
129 history.pushState(
130 estado, "", location.href
131 )
132 } catch (err) {
133 console.error(err)
134 }
135 }
136 })
137
138 window.addEventListener(
139 "popstate",
140 event => {
141 if (
142 typeof event.state === "string"
143 ) {
144 transicion(event.state)
145 }
146 }
147 )
148
149 history.replaceState(
150 "inicio", "", location.href
151 )
152
153 /**
154 * @param {string} estado
155 */
156 function muestraVista(estado) {
157 document.title =
158 titulos.get(estado) ?? ""
159 for (const vista of vistas) {
160 vista.hidden =
161 estado !== vista.id
162 }
163 }
164 /**
165 * @param {string} estado
166 */
167 function transicion(estado) {
168 if (
169 typeof document.startViewTransition === "function"
170 ) {
171 document.startViewTransition(
172 () => muestraVista(estado)
173 )
174 } else {
175 muestraVista(estado)
176 }
177 }
178
179 </script>
180
181</body>
182
183</html>

C. View transitions 1

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5
6 <meta charset="UTF-8">
7 <meta name="viewport"
8 content="width=device-width">
9 <title>View Transitions</title>
10
11 <style>
12 /*
13 https://www.w3.org/TR/css-view-transitions-2/
14 */
15
16 nav {
17 display: flex;
18 align-items: center;
19 flex-wrap: wrap;
20 align-content: center;
21 list-style-type: none;
22 gap: 0.5rem;
23 }
24
25 /* Activa transiciones de vistas
26 * entre documentos para esta
27 * página. */
28 @view-transition {
29 navigation: auto;
30 }
31
32 @keyframes aparece {
33 from {
34 opacity: 0;
35 }
36 }
37
38 @keyframes desvanece {
39 to {
40 opacity: 0;
41 }
42 }
43
44 /* Definición que aplicab a todas
45 * las definiciones de
46 * view-transition para root. */
47 ::view-transition-group(root) {
48 animation-duration: 1s;
49 }
50
51 ::view-transition-old(root) {
52 animation-name: desvanece;
53 }
54
55 ::view-transition-new(root) {
56 animation-delay: 1s;
57 animation-name: aparece;
58 }
59 </style>
60
61</head>
62
63<body>
64
65 <nav>
66 <a href="CviewTransitions1.html">
67 Inicio
68 </a>
69 <a href="DviewTransitions2.html">
70 Acerca de
71 </a>
72 </nav>
73
74 <main>
75 <h1>View Transitions</h1>
76 <p>
77 Esta es la página principal.
78 </p>
79 </main>
80
81 <footer>
82 <p>
83 © 2025
84 Gilberto Pacheco Gallegos.
85 </p>
86 </footer>
87
88</body>
89
90</html>

D. View transitions 2

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5
6 <meta charset="UTF-8">
7 <meta name="viewport"
8 content="width=device-width">
9 <title>
10 Aceca de - View Transitions
11 </title>
12
13 <style>
14 nav {
15 display: flex;
16 align-items: center;
17 flex-wrap: wrap;
18 align-content: center;
19 list-style-type: none;
20 gap: 0.5rem;
21 }
22
23 @view-transition {
24 navigation: auto;
25 }
26
27 main {
28 view-transition-name: main;
29 }
30
31 @keyframes desplazaALaDerecha {
32 from {
33 transform: translateX(100vw);
34 }
35 }
36
37 @keyframes desplazaALaIzquierda {
38 to {
39 transform: translateX(-100vw);
40 }
41 }
42
43 ::view-transition-group(main) {
44 animation-duration: 2s;
45 }
46
47 ::view-transition-old(main) {
48 animation-name:
49 desplazaALaIzquierda;
50 }
51
52 ::view-transition-new(main) {
53 animation-name:
54 desplazaALaDerecha;
55 }
56 </style>
57
58</head>
59
60<body>
61
62 <nav>
63 <a href="CviewTransitions1.html">
64 Inicio
65 </a>
66 <a href="DviewTransitions2.html">
67 Acerca de
68 </a>
69 </nav>
70
71 <main>
72 <h1>Acerca de</h1>
73 <p>
74 Esta es la página Acerca de.
75 </p>
76 </main>
77
78 <footer>
79 <p>
80 © 2025
81 Gilberto Pacheco Gallegos.
82 </p>
83 </footer>
84
85</body>
86
87</html>

E. Resumen