Ejercicio práctico 20: Formularios con Campos de Fecha y Número
Descubre cómo crear formularios HTML que incluyan campos de fecha <input type="date"> y número <input type="number">. Este ejercicio práctico te enseña a implementar controles de entrada modernos, útiles y accesibles para mejorar la experiencia del usuario en formularios web.
Actividad
Crea un formulario HTML que incluya campos de fecha <input type="date"> y número <input type="number">. Añade también un botón para enviar el formulario
Solución interactiva
Solución con el código HTML completo
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Formulario con Fecha y Número</title>
</head>
<body>
<h2>Formulario con Fecha y Número</h2>
<form>
<label for="nombre">Nombre:</label>
<input type="text" id="nombre" name="nombre" />
<br />
<label for="fecha-nacimiento">Fecha de Nacimiento:</label>
<input type="date" id="fecha-nacimiento" name="fecha-nacimiento" />
<br />
<label for="edad">Edad:</label>
<input type="number" id="edad" name="edad" min="1" max="120" />
<br />
<label for="email">Correo Electrónico:</label>
<input type="email" id="email" name="email" />
<br />
<button type="submit">Enviar</button>
</form>
</body>
</html>
Variantes del mismo ejercicio
Variante 1: Todos los tipos de fecha y hora
HTML5 ofrece varios tipos de input para fechas y horas, cada uno con un propósito específico. Este ejemplo muestra todos en un mismo formulario.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Tipos de Fecha y Hora</title>
<style>
form {
max-width: 500px;
}
label {
display: block;
margin-top: 16px;
font-weight: bold;
color: #333;
}
input {
width: 100%;
padding: 10px;
margin-top: 4px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
}
.ayuda {
font-size: 12px;
color: #888;
margin-top: 2px;
}
</style>
</head>
<body>
<h1>Tipos de Input para Fecha y Hora</h1>
<form>
<label for="fecha">📅 date — Fecha (día/mes/año):</label>
<input type="date" id="fecha" name="fecha" />
<p class="ayuda">Ej: 10/06/2026. Ideal para fechas de nacimiento.</p>
<label for="hora">⏰ time — Hora (horas:minutos):</label>
<input type="time" id="hora" name="hora" value="14:30" />
<p class="ayuda">Ej: 14:30. Útil para horarios de turnos o reservas.</p>
<label for="fecha-hora">📆 datetime-local — Fecha y hora juntas:</label>
<input type="datetime-local" id="fecha-hora" name="fecha-hora" />
<p class="ayuda">Ej: 10/06/2026 14:30. Para eventos con fecha y horario preciso.</p>
<label for="mes">🗓️ month — Mes y año:</label>
<input type="month" id="mes" name="mes" />
<p class="ayuda">Ej: Junio 2026. Para seleccionar vencimientos de tarjeta.</p>
<label for="semana">📊 week — Semana del año:</label>
<input type="week" id="semana" name="semana" />
<p class="ayuda">Ej: Semana 24, 2026. Útil en planillas y reportes semanales.</p>
<button type="submit" style="margin-top: 24px; padding: 12px 28px; background: #007bff; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px;">
Enviar
</button>
</form>
</body>
</html>
Compatibilidad: date y time funcionan en todos los navegadores modernos. datetime-local, month y week tienen soporte ligeramente menor en Safari. Siempre probá en múltiples navegadores.
Variante 2: Inputs numéricos avanzados (range, tel, color)
Además de type="number", HTML ofrece otros tipos de entrada para datos numéricos o especializados.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Inputs Numéricos</title>
<style>
form {
max-width: 500px;
}
label {
display: block;
margin-top: 16px;
font-weight: bold;
}
input {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
margin-top: 4px;
}
input[type="range"] {
width: 100%;
padding: 0;
}
.rango-valores {
display: flex;
justify-content: space-between;
font-size: 12px;
color: #888;
margin-top: 2px;
}
.precio-actual {
font-size: 20px;
color: #28a745;
font-weight: bold;
margin-left: 12px;
}
</style>
</head>
<body>
<h1>Tipos de Input Numéricos y Especializados</h1>
<form>
<label for="edad">🔢 number — Edad:</label>
<input type="number" id="edad" name="edad" min="1" max="120" value="25" />
<label for="precio">
📊 range — Precio máximo:
<span class="precio-actual" id="precio-valor">$500</span>
</label>
<input
type="range"
id="precio"
name="precio"
min="0"
max="1000"
step="10"
value="500"
oninput="document.getElementById('precio-valor').textContent = '$' + this.value"
/>
<div class="rango-valores">
<span>$0</span>
<span>$1000</span>
</div>
<label for="telefono">📱 tel — Número de teléfono:</label>
<input type="tel" id="telefono" name="telefono" placeholder="+54 11 1234-5678"
pattern="[+]{0,1}[0-9]{1,4}[ ]{0,1}[0-9]{1,4}[ ]{0,1}[0-9]{1,4}[ ]{0,1}[0-9]{1,4}" />
<label for="color">🎨 color — Color favorito:</label>
<input type="color" id="color" name="color" value="#007bff" />
<label for="url">🔗 url — Sitio web:</label>
<input type="url" id="url" name="url" placeholder="https://tusitio.com" />
<button type="submit" style="margin-top: 24px; padding: 12px 28px; background: #28a745; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 16px;">
Guardar Preferencias
</button>
</form>
</body>
</html>
El type="range" es ideal para filtros de precio, volumen, brillo o cualquier valor en un espectro. type="color" abre el selector de color nativo del sistema operativo.
Variante 3: Formulario completo con validación HTML5
La validación nativa de HTML5 evita tener que escribir JavaScript para las validaciones más comunes. Con los atributos correctos, el navegador se encarga del resto.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Formulario con Validación</title>
<style>
form {
max-width: 520px;
background: #fafafa;
padding: 30px;
border-radius: 12px;
border: 1px solid #e0e0e0;
}
label {
display: block;
margin-top: 18px;
font-weight: 600;
color: #333;
}
label span {
color: #dc3545;
}
input, textarea {
width: 100%;
padding: 10px 12px;
margin-top: 4px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
font-family: Arial, sans-serif;
box-sizing: border-box;
}
input:invalid, textarea:invalid {
border-color: #dc3545;
background: #fff5f5;
}
input:valid, textarea:valid {
border-color: #28a745;
background: #f0fff4;
}
.error-msg {
font-size: 12px;
color: #dc3545;
margin-top: 2px;
display: none;
}
input:invalid + .error-msg {
display: block;
}
button {
margin-top: 24px;
width: 100%;
padding: 14px;
background: #007bff;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: bold;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
</style>
</head>
<body>
<h1>Formulario de Registro</h1>
<p>Los campos con <span style="color: #dc3545;">*</span> son obligatorios.</p>
<form novalidate>
<label for="nombre">Nombre completo <span>*</span></label>
<input
type="text"
id="nombre"
name="nombre"
required
minlength="3"
maxlength="50"
placeholder="Ej: Gabriel Maza"
autocomplete="name"
/>
<p class="error-msg">El nombre debe tener entre 3 y 50 caracteres.</p>
<label for="email">Correo electrónico <span>*</span></label>
<input
type="email"
id="email"
name="email"
required
placeholder="Ej: usuario@dominio.com"
autocomplete="email"
/>
<p class="error-msg">Ingresá un correo electrónico válido.</p>
<label for="password">Contraseña <span>*</span></label>
<input
type="password"
id="password"
name="password"
required
minlength="8"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
placeholder="Mínimo 8 caracteres, 1 mayúscula, 1 minúscula, 1 número"
autocomplete="new-password"
/>
<p class="error-msg">
La contraseña debe tener al menos 8 caracteres, una mayúscula, una minúscula y un número.
</p>
<label for="fecha-nacimiento">Fecha de nacimiento <span>*</span></label>
<input
type="date"
id="fecha-nacimiento"
name="fecha-nacimiento"
required
max="2010-12-31"
/>
<p class="error-msg">Debés ser mayor de 16 años (fecha anterior a 2010).</p>
<label for="telefono">Teléfono</label>
<input
type="tel"
id="telefono"
name="telefono"
pattern="[+]{0,1}[0-9]{7,15}"
placeholder="+541112345678"
autocomplete="tel"
/>
<p class="error-msg">Ingresá un número de teléfono válido (7 a 15 dígitos).</p>
<label for="url">URL de portfolio</label>
<input
type="url"
id="url"
name="url"
placeholder="https://tuportfolio.com"
autocomplete="url"
/>
<p class="error-msg">Ingresá una URL válida que comience con http:// o https://.</p>
<label for="comentarios">Comentarios adicionales</label>
<textarea
id="comentarios"
name="comentarios"
rows="4"
maxlength="500"
placeholder="Escribí tus comentarios acá (máximo 500 caracteres)..."
></textarea>
<button type="submit">✅ Registrarse</button>
</form>
</body>
</html>
Atributos de validación clave:
required— campo obligatoriominlength/maxlength— largo mínimo/máximo de textomin/max— valor numérico mínimo/máximopattern— expresión regular para validar el formatoautocomplete— sugiere al navegador qué tipo de dato autocompletar
Variante 4: Formulario con fieldset, legend y datalist
Los formularios largos se benefician de estar organizados en grupos lógicos con <fieldset> y <legend>. Además, <datalist> ofrece sugerencias mientras el usuario escribe.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Formulario con Fieldset</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
fieldset {
border: 2px solid #e0e0e0;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
}
legend {
font-weight: bold;
font-size: 18px;
color: #333;
padding: 0 10px;
}
label {
display: block;
margin-top: 12px;
font-weight: 600;
}
input, select {
width: 100%;
padding: 8px 12px;
margin-top: 4px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
box-sizing: border-box;
}
button {
padding: 12px 32px;
background: #007bff;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
}
button[type="reset"] {
background: #6c757d;
}
</style>
</head>
<body>
<h1>Reserva de Viaje</h1>
<form>
<fieldset>
<legend>👤 Datos Personales</legend>
<label for="nombre">Nombre completo</label>
<input type="text" id="nombre" name="nombre" required />
<label for="email">Correo electrónico</label>
<input type="email" id="email" name="email" required />
<label for="pais">País de residencia</label>
<input
type="text"
id="pais"
name="pais"
list="lista-paises"
placeholder="Escribí tu país..."
/>
<datalist id="lista-paises">
<option value="Argentina" />
<option value="Brasil" />
<option value="Chile" />
<option value="Colombia" />
<option value="España" />
<option value="México" />
<option value="Perú" />
<option value="Uruguay" />
<option value="Venezuela" />
<option value="Estados Unidos" />
</datalist>
<p style="font-size:12px; color:#888; margin-top: 4px;">
Escribí las primeras letras y seleccioná de la lista.
</p>
</fieldset>
<fieldset>
<legend>✈️ Detalles del Viaje</legend>
<label for="destino">Destino (escribí tu ciudad)</label>
<input type="text" id="destino" name="destino" list="lista-destinos" placeholder="Escribí tu destino..." />
<datalist id="lista-destinos">
<option value="Buenos Aires" />
<option value="Cancún" />
<option value="Madrid" />
<option value="Nueva York" />
<option value="París" />
<option value="Río de Janeiro" />
<option value="Roma" />
<option value="Tokio" />
</datalist>
<label for="fecha-ida">Fecha de ida</label>
<input type="date" id="fecha-ida" name="fecha-ida" required />
<label for="fecha-vuelta">Fecha de vuelta</label>
<input type="date" id="fecha-vuelta" name="fecha-vuelta" required />
<label for="pasajeros">Cantidad de pasajeros</label>
<input type="number" id="pasajeros" name="pasajeros" min="1" max="10" value="1" />
<label for="clase">Clase</label>
<select id="clase" name="clase">
<option value="economy">Económica</option>
<option value="premium">Premium Economy</option>
<option value="business">Business</option>
<option value="first">Primera Clase</option>
</select>
</fieldset>
<div style="display: flex; gap: 12px;">
<button type="submit">🔍 Buscar Vuelos</button>
<button type="reset">🗑️ Limpiar</button>
</div>
</form>
</body>
</html>
<datalist> es una funcionalidad subestimada de HTML5. Proporciona sugerencias de autocompletado sin JavaScript, combinando lo mejor de un <input> libre y un <select>.
Buenas y Malas Prácticas
| ✅ Buena práctica | ❌ Mala práctica |
|---|---|
Siempre vincular <label for="..."> con el id del input | Usar solo placeholder como etiqueta (desaparece al escribir) |
Usar type="email", type="tel", type="url" según corresponda | Usar type="text" para todo (perdés validación y teclados táctiles) |
Agregar required y min/max para validación nativa | Depender solo de JavaScript para validaciones básicas |
Organizar formularios largos con <fieldset> y <legend> | Dejar todos los campos en un solo bloque sin agrupación lógica |
Usar autocomplete para mejorar la experiencia del usuario | Dejar autocomplete="off" en campos donde el navegador puede ayudar |
Usar pattern con expresiones regulares claras | Crear patterns demasiado restrictivos que rechazan datos válidos |
Preguntas Frecuentes (FAQ)
¿Los inputs de tipo date, time y number funcionan en todos los navegadores?
Sí, en todos los navegadores modernos (Chrome, Firefox, Safari, Edge desde 2020). En navegadores muy antiguos (IE11), estos inputs se degradan a type="text". Para proyectos que deban soportar IE11, necesitás un polyfill o usar una biblioteca de componentes (React Datepicker, Flatpickr).
¿Qué diferencia hay entre type="number" y type="tel"?
type="number" muestra teclado numérico con decimales y acepta los atributos min, max y step. type="tel" muestra un teclado telefónico (ideal para móviles) y no fuerza restricciones numéricas, lo que permite caracteres como +, (, ), - y espacios. Usá number para cantidades y tel para números de teléfono.
¿Es suficiente la validación HTML5 o necesito JavaScript?
La validación HTML5 cubre el 80% de los casos (campos requeridos, formato de email, rangos numéricos). Para validaciones más complejas (ej: "la fecha de vuelta debe ser posterior a la de ida", "el nombre de usuario no debe estar en uso"), necesitás JavaScript. La mejor estrategia es combinar validación HTML5 (primera línea) + JavaScript (validaciones personalizadas) + validación del lado del servidor (seguridad).
¿<datalist> reemplaza a <select>?
No. <select> fuerza al usuario a elegir una opción de una lista cerrada. <datalist> solo sugiere opciones; el usuario puede escribir cualquier valor. Usá <select> cuando las opciones son fijas (ej: país, mes, categoría) y <datalist> cuando querés sugerir pero permitir libertad (ej: buscador de ciudades, tags).
📘 Conocé más a fondo este tema acá 👉 Creación de formularios con HTML.