13. Formularios

Versión para imprimir.

A. Todo lo que hay

Este es un ejemplo típico de un formulario HTML.

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 <title>Formulario</title>
8 <meta name="viewport"
9 content="width=device-width">
10
11 <style>
12 body {
13 font-family: sans-serif;
14 }
15
16 form {
17 max-width: 900px;
18 margin-inline: auto;
19 }
20
21 label,
22 legend {
23 font-weight: bold;
24 }
25
26 fieldset label {
27 font-weight: normal;
28 }
29
30 label:has(:not([type="radio"]):required)::before {
31 content: "✳ ";
32 }
33
34 label:has(:not([type="radio"]):invalid)::before {
35 content: "❌ ";
36 }
37
38 label:has(:not([type="radio"]):invalid:required)::before {
39 content: "✳ ❌ ";
40 }
41
42 label output,
43 label input:not([type="checkbox"], [type="radio"], [type="range"]),
44 label select,
45 label textarea {
46 display: block;
47 box-sizing: border-box;
48 width: 100%;
49 }
50
51 label:has([type="range"]) {
52 white-space: pre-wrap;
53 }
54
55 fieldset {
56 box-sizing: border-box;
57 }
58
59 fieldset p {
60 margin-block: 0.5rem;
61 }
62
63 fieldset label:has(:invalid)::after {
64 content: "❌";
65 }
66
67 legend:has(~p :required)::before {
68 content: "✳ ";
69 }
70
71 input[name="temperatura2"] {
72 writing-mode: vertical-lr;
73 }
74 </style>
75
76</head>
77
78<body>
79
80 <form id="forma">
81
82 <h1>Formulario</h1>
83
84 <p>
85 <label>
86 Nombre
87 <output name="nombre">Pp</output>
88 </label>
89 </p>
90
91 <p>
92 <label accesskey="A">
93 Apellidos
94 <input name="apellidos" type="text" placeholder="ej. Pérez López"
95 required>
96 <small>Los apellidos de tu familia</small>
97 </label>
98 </p>
99
100 <input name="clave" type="hidden" value="">
101
102 <p>
103 <label>
104 Restaurante favorito
105 <input name="apellidos" type="text" value="La cabaña del Tio Jese">
106 </label>
107 </p>
108
109 <p>
110 <label>
111 Número telefónico
112 <input name="telefono" type="tel">
113 </label>
114 </p>
115
116 <p>
117 <label>
118 Número de tarjeta
119 <input name="tarjeta" type="text" pattern="\d{14,19}" inputmode="numeric">
120 <small>14 a 19 letras o caracteres.</small>
121 </label>
122 </p>
123
124 <p>
125 <label>
126 Sitio personal
127 <input name="sitio" type="url" list="sitios">
128 </label>
129 </p>
130 <datalist id="sitios">
131 <option>https://facebook.com</option>
132 <option>https://google.com</option>
133 <option>https://tiktok.com</option>
134 <option>https://youtube.com</option>
135 </datalist>
136 <p>
137 <label>
138 Email para quejas
139 <input name="quejas" type="email">
140 </label>
141 </p>
142
143 <p>
144 <label>
145 Match
146 <input name="match" type="password" required pattern="\w{4,7}">
147 </label>
148 <small>4 a 7 letras o caracteres.</small>
149 </p>
150
151 <p>
152 <label>
153 Próximo día festivo
154 <input name="proximo" type="date">
155 </label>
156 </p>
157
158 <p>
159 <label>
160 Próximo día libre
161 <input name="libre" type="date" value="2025-02-14" min="2025-01-01"
162 max="2025-06-01" step="2">
163 </label>
164 </p>
165
166 <p>
167 <label>
168 Mes
169 <input name="mes" type="month" value="2025-04" min="2025-01" max="2025-12"
170 step="3">
171 </label>
172 </p>
173
174 <p>
175 <label>
176 Semana de vacaciones
177 <input name="vacaciones" type="week" value="2025-W05" min="2025-W01"
178 max="2025-W54" step="2">
179 </label>
180 </p>
181
182 <p>
183 <label>
184 Hora de la reunión
185 <input name="horaReunion" type="time" value="15:30" min="07:00"
186 max="17:30" step="1800">
187 </label>
188 </p>
189
190 <p>
191 <label>
192 Fecha y hora local
193 <input name="nacimiento" type="datetime-local" value="2025-03-18T15:00"
194 min="2025-01-01T10:00" max="2025-12-31T22:00" step="3600">
195 </label>
196 </p>
197
198 <p>
199 <label>
200 Altura
201 <input name="altura" type="number" min="0.5" max="3.0" step="0.01">
202 </label>
203 </p>
204
205 <p>
206 <label>
207 Temperatura
208 -50 <input name="temperatura" type="range" min="-50" max="80" step="10"
209 value="20"> 80</label>
210 </p>
211
212 <p>
213 <label>
214 Temperatura 2
215 -50
216 <input name="temperatura2" type="range" min="-50" max="80"
217 value="20" list="temperaturas">
218 80</label>
219 </p>
220 <datalist id="temperaturas">
221 <option value="-50">Congelado</option>
222 <option value="-30"></option>
223 <option value="0"></option>
224 <option value="30"></option>
225 <option value="50"></option>
226 <option value="80">Quemándose</option>
227 </datalist>
228 <p>
229 <label>
230 Color
231 <input name="color" type="color" colorspace="limited-srgb" value="#00ff00">
232 </label>
233 </p>
234
235 <p>
236 <label>
237 Tarea
238 <input name="tarea" type="file" accept="image/*,application/pdf">
239 </label>
240 </p>
241
242 <p>
243 <label>
244 <input name="aprobado" type="checkbox">
245 Aprobado
246 </label>
247 </p>
248
249 <fieldset>
250 <legend>Pasatiempos</legend>
251 <p>
252 <label>
253 <input type="checkbox" name="pasatiempos[]" value="fut">
254 Futbol
255 </label>
256 </p>
257 <p>
258 <label>
259 <input type="checkbox" name="pasatiempos[]" value="chess" checked>
260 Ajedrez
261 </label>
262 </p>
263 <p>
264 <label>
265 <input type="checkbox" name="pasatiempos[]" value="basket" checked>
266 Basketbol
267 </label>
268 </p>
269 </fieldset>
270
271 <fieldset>
272 <legend>Madrugador</legend>
273 <p>
274 <label><input type="radio" name="madrugador" value="si" checked>Si</label>
275 <label><input type="radio" name="madrugador" value="no">No</label>
276 </p>
277 </fieldset>
278
279 <fieldset>
280 <legend>Tamaño</legend>
281 <p>
282 <label>
283 <input type="radio" name="tamano" value="grande" required>
284 Grande
285 </label>
286 </p>
287 <p>
288 <label>
289 <input type="radio" name="tamano" value="mediano">
290 Mediano
291 </label>
292 </p>
293 <p>
294 <label>
295 <input type="radio" name="tamano" value="chico">
296 Chico
297 </label>
298 </p>
299 </fieldset>
300
301 <p>
302 <label>
303 Género Musical
304 <select name="generoMusical" required>
305 <option value="">Sin selección</option>
306 <option value="pop">Pop</option>
307 <option value="reg">Reguetón</option>
308 </select>
309 </label>
310 </p>
311
312 <p>
313 <label>
314 Géneración
315 <select name="generacion" value="Z">
316 <option value="boom">Baby Boom</option>
317 <option value="X">X</option>
318 <option value="">Sin selección</option>
319 <option value="Y">Millenoals</option>
320 <option value="Z">Z</option>
321 <option value="alfa">Alfa</option>
322 </select>
323 </label>
324 </p>
325
326 <p>
327 <label>
328 Género
329 <select name="genero">
330 <option value="masculino">Masculino</option>
331 <option value="femenino" selected>Femenino</option>
332 <option value="">-- Seleccionar --</option>
333 <optgroup label="Otros">
334 <option value="nodecir">Prefiero no decirlo</option>
335 <option value="nobinario">No binario</option>
336 </optgroup>
337 </select>
338 </label>
339 </p>
340
341 <p>
342 <label>
343 Bebidas
344 <select name="bebidas[]" multiple size="3">
345 <option value="cafe" selected>Café</option>
346 <option value="agua" selected>Agua</option>
347 <option value="limonada">Limonada</option>
348 </select>
349 </label>
350 </p>
351
352 <p>
353 <label>
354 Mi camino desde casa
355 <textarea name="camino" required rows="10" cols="25"></textarea>
356 </label>
357 </p>
358
359 <p>
360 <label>
361 Mi opinión sobre la comida mexicana
362 <textarea name="opinion" rows="10" cols="25">Es muy rica</textarea>
363 </label>
364 </p>
365
366 <p><small>✳ Obligatorio</small></p>
367
368 <p>
369 <button type="submit">Procesar</button>
370 <button type="reset">Reiniciar</button>
371 </p>
372
373 </form>
374
375</body>
376
377</html>

Solo para los más rudos

B. Formulario simple

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport"
7 content="width=device-width">
8 <title>Saludo</title>
9</head>
10
11<body>
12 <!--
13 form
14 Captura los datos para un
15 cálculo.
16 action="javascript:calcula()"
17 Al activar la forma, se ejecuta
18 la función
19 calcula()
20 de la etiqueta
21 <script>
22 que aparece más abajo. -->
23 <form
24 action="javascript:calcula()">
25 <h1>Saludo</h1>
26 <!--
27 Los elementos de captura se
28 pueden colocan cada uno en un
29 <p> -->
30 <p>
31 <!--
32 label
33 Pone el rótulo
34 Nombre
35 que aparece más abajo, al
36 elemento
37 input
38 que también aparece más abajo.
39 -->
40 <label>
41 Nombre
42 <!--
43 input
44 Campo de captura. Activa la
45 forma al teclear
46 «intro»
47 cuando tiene el cursor.
48 type="text"
49 Captura texto
50 id="inNombre"
51 Identificador del campo de
52 captura. Se puede usar desde
53 el elemento
54 <script>
55 más abajo.
56 required
57 Este campo no se puede quedar
58 en blanco. -->
59 <input type="text"
60 id="inNombre" required>
61 </label>
62 </p>
63 <p>
64 <!--
65 button
66 Activa la forma al hacerle
67 click o presionado la tecla
68 espacio cuando tiene el
69 tabulador. -->
70 <button>Calcular</button>
71 </p>
72 </form>
73 <script>
74 /**
75 * Función que realiza el cálculo
76 * cuando se activa la forma.
77 */
78 function calcula() {
79 /* Recupera el texto capturado
80 * en "inNombre" y lo asigna
81 * a la constante "nombre". */
82 const nombre = inNombre.value
83 const saludo = saluda(nombre)
84 /* Despliega el saludo en un
85 * cuadro de diálogo. */
86 alert(saludo);
87 }
88
89 /**
90 * Función que realiza la lógica
91 * del cálculo.
92 * @param {string} nombre
93 */
94 function saluda(nombre) {
95 return `Hola ${nombre}.`
96 }
97 </script>
98</body>
99
100</html>

C. El elemento form

Solo para los más rudos

D. Atributos comunes

E. El elemento label

Solo para los más rudos

F. El elemento button

Solo para los más rudos

G. El elemento input

Otros atributos

valueAsNumber
  • Propiedad de JavaScript para asignar o recuperar el valor numérico de captura.

  • Para controles numéricos del elemento input.

  • Devuelve un número.

  • Si el texto es una cadena vacía o no representa un número, el valor devuelto es NaN (o sea que no es un número).

pattern
  • Para los tipos que manejan texto.

  • Expresión regular para validar el contenido. Abarca desde el inicio hasta el final del texto.

min
  • Para controles numéricos y de fecha.

  • Valor mínimo que se puede capturar.

max
  • Para controles numéricos y de fecha.

  • Valor máximo que se puede capturar.

step
  • Para controles numéricos y de fecha.

  • Granularidad o separación entre los valores que se pueden capturar. Por ejemplo, step=0.1 indica que los valores pueden ser 0, 0.1, 0.2, 0.3, etcétera. Aplica también para fechas.

  • El valor por omisión para controles numéricos es 1.

Solo para los más rudos

H. El elemento output

Solo para los más rudos

I. División

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport"
7 content="width=device-width">
8 <title>División</title>
9</head>
10
11<body>
12 <form
13 action="javascript:procesa()">
14 <h1>División</h1>
15 <p>
16 <label>
17 a
18 <input id="inA"
19 type="number"
20 step="0.1"
21 required>
22 </label>
23 </p>
24 <p>
25 <label>
26 b
27 <input id="inB"
28 type="number"
29 step="0.1"
30 required
31 oninput="validaB()">
32 </label>
33 </p>
34 <p>
35 <button>Dividir</button>
36 </p>
37 </form>
38 <script>
39 const NO_0 = "No puede ser 0"
40
41 function validaB() {
42 const b = inB.valueAsNumber
43 /* Debe cumplirse que b
44 * sea un número diferente
45 * de 0. */
46 if (isNaN(b) || b !== 0) {
47 inB.setCustomValidity("")
48 } else {
49 inB.setCustomValidity(NO_0)
50 }
51 }
52
53 function procesa() {
54 const a = inA.valueAsNumber
55 const b = inB.valueAsNumber
56 const resultado = divide(a, b)
57 alert(
58 `${a} / ${b} = ${resultado}`)
59 }
60
61 /**
62 * @param {number} a
63 * @param {number} b
64 */
65 function divide(a, b) {
66 return a / b
67 }
68 </script>
69</body>
70
71</html>

J. Formulario numérico de 2 botones

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport"
7 content="width=device-width">
8 <title>
9 Formulario con 2 botones
10 </title>
11</head>
12
13<body>
14 <form
15 action=javascript:procSuma()>
16 <h1>
17 Formulario con 2 botones
18 </h1>
19 <p>
20 <label>
21 a
22 <input id=inA type=number
23 required min="0.1" max="100"
24 step="0.1">
25 </label>
26 </p>
27 <p>
28 <label>
29 b
30 <input id=inB type=number
31 required min="0.1" max="100"
32 step="0.1">
33 </label>
34 </p>
35 <p>
36 <button>Sumar</button>
37 <button formaction="javascript:
38 procResta()">
39 Restar
40 </button>
41 </p>
42 </form>
43 <script>
44 function procSuma() {
45 const a = inA.valueAsNumber
46 const b = inB.valueAsNumber
47 const resultado = suma(a, b)
48 alert(
49 `${a} + ${b} = ${resultado}`)
50 }
51
52 function procResta() {
53 const a = inA.valueAsNumber
54 const b = inB.valueAsNumber
55 const resultado = resta(a, b)
56 alert(
57 `${a} - ${b} = ${resultado}`)
58 }
59
60 function suma(a, b) {
61 return a + b
62 }
63
64 function resta(a, b) {
65 return a - b
66 }
67 </script>
68</body>
69
70</html>

K. Recomendaciones

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport"
7 content="width=device-width">
8 <title>Recomendaciones</title>
9</head>
10
11<body>
12 <form
13 action="javascript:procesa()">
14 <h1>Recomendaciones</h1>
15 <p>
16 <label>
17 Género
18 <select id="inGenero" required>
19 <option value="">
20 -- Selecciona --
21 </option>
22 <option value="pop">
23 Pop
24 </option>
25 <option value="reg">
26 Reguetón
27 </option>
28 </select>
29 </label>
30 </p>
31 <p>
32 <button>Recomendar</button>
33 </p>
34 </form>
35 <script>
36 function procesa() {
37 const genero = inGenero.value
38 const resultado =
39 recomienda(genero)
40 alert(resultado)
41 }
42
43 /** @param {string} genero */
44 function recomienda(genero) {
45 if (genero === "pop") {
46 return "Para el pop te " +
47 "recomiendo a Dua Lipa."
48 } else if (genero === "reg") {
49 return "Para el reguetón te " +
50 "recomiendo a Bad Bunny."
51 }
52 }
53 </script>
54</body>
55
56</html>

Solo para los más rudos

L. Adivina

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport"
7 content="width=device-width">
8 <title>Adivina</title>
9 <style>
10 html {
11 font-family: sans-serif;
12 text-align: center;
13 }
14
15 img {
16 max-height: 40vh;
17 max-width: 100%;
18 }
19 </style>
20</head>
21
22<body>
23 <h1>Adivina</h1>
24 <figure>
25 <img src="https://media.giphy.com/media/JKNn9A98JBVlu/giphy.gif"
26 alt="Imagen de un animal">
27 <figcaption>
28 ¿Qúe animal es este?
29 </figcaption>
30 </figure>
31 <p>
32 <button onclick="rana()">
33 Una Rana
34 </button>
35 <button onclick="oso()">
36 Un Oso
37 </button>
38 </p>
39 <script>
40 function rana() {
41 alert(
42 "Claro que no es una rana.")
43 }
44
45 function oso() {
46 alert("Claro que si es un oso.")
47 }
48 </script>
49</body>
50
51</html>

M. Encuesta

Salida

Ábrelo en otra pestaña.

Revísalo en gilpgedit.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport"
7 content="width=device-width">
8 <title>¿Cuál te gusta más?</title>
9 <style>
10 html {
11 font-family: sans-serif;
12 }
13
14 body {
15 display: grid;
16 gap: 0.5rem;
17 margin: 0;
18 padding: 0.5rem;
19 max-height: 100vh;
20 overflow: hidden;
21 grid-template-columns:
22 1fr 1fr 1fr 1fr;
23 grid-template-areas:
24 "h1 h1 h1 h1"
25 "outGatito btnGatito outPerrito btnPerrito"
26 "imgGatito imgGatito imgPerrito imgPerrito";
27 }
28
29 h1 {
30 grid-area: h1;
31 text-align: center;
32 }
33
34 #outGatito {
35 grid-area: outGatito;
36 justify-self: center;
37 }
38
39 #btnGatito {
40 grid-area: btnGatito;
41 }
42
43 #imgGatito {
44 grid-area: imgGatito;
45 width: 100%;
46 }
47
48 #outPerrito {
49 grid-area: outPerrito;
50 justify-self: center;
51 }
52
53 #btnPerrito {
54 grid-area: btnPerrito;
55 }
56
57 #imgPerrito {
58 grid-area: imgPerrito;
59 width: 100%;
60 }
61 </style>
62</head>
63
64<body>
65 <h1>¿Cuál te gusta más?</h1>
66 <output id="outGatito">
67 0 votos
68 </output>
69 <button id="btnGatito"
70 onclick="gatito()">
71 Vota
72 </button>
73 <img id="imgGatito" alt="Gatito"
74 src="https://media.giphy.com/media/uWYjSbkIE2XIMIc7gh/giphy.gif">
75 <output id=outPerrito>
76 0 votos
77 </output>
78 <button id="btnPerrito"
79 onclick=perrito()>
80 Vota
81 </button>
82 <img id="imgPerrito"
83 alt="Perrito"
84 src="https://media.giphy.com/media/rXzOY4RpSA0Ug/giphy.gif">
85 <script>
86 let votosGatito = 0
87 let votosPerrito = 0
88
89 function gatito() {
90 votosGatito++
91 outGatito.value =
92 `${votosGatito} votos`
93 }
94
95 function perrito() {
96 votosPerrito++
97 outPerrito.value =
98 `${votosPerrito} votos`
99 }
100 </script>
101</body>
102
103</html>

N. Recomienda

Salida

Ábrelo en otra pestaña.

1<!DOCTYPE html>
2<html lang="es">
3
4<head>
5 <meta charset="utf-8">
6 <meta name="viewport"
7 content="width=device-width">
8 <title>Recomienda</title>
9 <style>
10 html {
11 font-family: sans-serif;
12 }
13
14 body {
15 display: grid;
16 gap: 0.5rem;
17 margin: 0;
18 padding: 0.5rem;
19 max-height: 100vh;
20 grid-template-columns:
21 8rem 2fr;
22 grid-template-areas:
23 "h1 h1"
24 "ul section";
25 }
26
27 h1 {
28 grid-area: h1;
29 text-align: center;
30 }
31
32 ul {
33 grid-area: ul;
34 }
35
36 section {
37 grid-area: section;
38 }
39
40 figure {
41 display: none;
42 flex: 1;
43 margin: 0;
44 width: 100%;
45 }
46
47 figure:target {
48 display: block;
49 }
50
51 img {
52 flex: 1;
53 width: 100%;
54 }
55 </style>
56</head>
57
58<body>
59 <h1>Recomienda</h1>
60 <ul>
61 <li>
62 <p>
63 <a href="#pop">Pop</a>
64 </p>
65 </li>
66 <li>
67 <p>
68 <a href="#reg">Reguetón</a>
69 </p>
70 </li>
71 </ul>
72 <section>
73 <figure id="pop">
74 <figcaption>
75 Para el pop te recomiendo a
76 Dua Lipa.
77 </figcaption>
78 <img alt="Gif de Dua Lipa"
79 src="https://media.giphy.com/media/3o7WIQin38ZjlwiKOs/giphy.gif">
80 </figure>
81 <figure id="reg">
82 <figcaption>
83 Para el reguetón te recomiendo
84 a Bad Bunny.
85 </figcaption>
86 <img alt="Gif de Bad Bunny"
87 src="https://media.giphy.com/media/kfcsiSjQUyMvEZ1khq/giphy.gif">
88 </figure>
89 </section>
90</body>
91
92</html>

O. Resumen