Practical Exercise 20: Forms with Date and Number Fields
Discover how to create HTML forms that include date fields <input type="date"> and number fields <input type="number">. This practical exercise teaches you how to implement modern, useful, and accessible input controls to improve the user experience in web forms.
Activity
Create an HTML form that includes date fields <input type="date"> and number fields <input type="number">. Also add a button to submit the form.
Interactive Solution
Solution with complete HTML code
<!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>
Variants of the Same Exercise
Variant 1: All Date and Time Types
HTML5 offers several input types for dates and times, each with a specific purpose. This example shows them all in one form.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Date and Time Types</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>Date and Time Input Types</h1>
<form>
<label for="fecha">📅 date — Date (day/month/year):</label>
<input type="date" id="fecha" name="fecha" />
<p class="ayuda">Ex: 06/10/2026. Ideal for birth dates.</p>
<label for="hora">⏰ time — Time (hours:minutes):</label>
<input type="time" id="hora" name="hora" value="14:30" />
<p class="ayuda">Ex: 14:30. Useful for appointment or reservation times.</p>
<label for="fecha-hora">📆 datetime-local — Date and time together:</label>
<input type="datetime-local" id="fecha-hora" name="fecha-hora" />
<p class="ayuda">Ex: 06/10/2026 14:30. For events with precise date and time.</p>
<label for="mes">🗓️ month — Month and year:</label>
<input type="month" id="mes" name="mes" />
<p class="ayuda">Ex: June 2026. For selecting card expiration dates.</p>
<label for="semana">📊 week — Week of the year:</label>
<input type="week" id="semana" name="semana" />
<p class="ayuda">Ex: Week 24, 2026. Useful in spreadsheets and weekly reports.</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;">
Submit
</button>
</form>
</body>
</html>
Compatibility: date and time work in all modern browsers. datetime-local, month, and week have slightly lower support in Safari. Always test in multiple browsers.
Variant 2: Advanced Numeric Inputs (range, tel, color)
In addition to type="number", HTML offers other input types for numeric or specialized data.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Numeric Inputs</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>Numeric and Specialized Input Types</h1>
<form>
<label for="edad">🔢 number — Age:</label>
<input type="number" id="edad" name="edad" min="1" max="120" value="25" />
<label for="precio">
📊 range — Maximum price:
<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 — Phone number:</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 — Favorite color:</label>
<input type="color" id="color" name="color" value="#007bff" />
<label for="url">🔗 url — Website:</label>
<input type="url" id="url" name="url" placeholder="https://yoursite.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;">
Save Preferences
</button>
</form>
</body>
</html>
type="range" is ideal for price filters, volume, brightness, or any value on a spectrum. type="color" opens the operating system's native color picker.
Variant 3: Complete Form with HTML5 Validation
Native HTML5 validation avoids writing JavaScript for the most common validations. With the right attributes, the browser handles the rest.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Form with Validation</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>Registration Form</h1>
<p>Fields marked with <span style="color: #dc3545;">*</span> are required.</p>
<form novalidate>
<label for="nombre">Full name <span>*</span></label>
<input
type="text"
id="nombre"
name="nombre"
required
minlength="3"
maxlength="50"
placeholder="Ex: Gabriel Maza"
autocomplete="name"
/>
<p class="error-msg">Name must be between 3 and 50 characters.</p>
<label for="email">Email <span>*</span></label>
<input
type="email"
id="email"
name="email"
required
placeholder="Ex: user@domain.com"
autocomplete="email"
/>
<p class="error-msg">Enter a valid email address.</p>
<label for="password">Password <span>*</span></label>
<input
type="password"
id="password"
name="password"
required
minlength="8"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
placeholder="Min 8 characters, 1 uppercase, 1 lowercase, 1 number"
autocomplete="new-password"
/>
<p class="error-msg">
Password must be at least 8 characters, with one uppercase, one lowercase, and one number.
</p>
<label for="fecha-nacimiento">Date of birth <span>*</span></label>
<input
type="date"
id="fecha-nacimiento"
name="fecha-nacimiento"
required
max="2010-12-31"
/>
<p class="error-msg">You must be over 16 years old (date before 2010).</p>
<label for="telefono">Phone</label>
<input
type="tel"
id="telefono"
name="telefono"
pattern="[+]{0,1}[0-9]{7,15}"
placeholder="+541112345678"
autocomplete="tel"
/>
<p class="error-msg">Enter a valid phone number (7 to 15 digits).</p>
<label for="url">Portfolio URL</label>
<input
type="url"
id="url"
name="url"
placeholder="https://yourportfolio.com"
autocomplete="url"
/>
<p class="error-msg">Enter a valid URL starting with http:// or https://.</p>
<label for="comentarios">Additional comments</label>
<textarea
id="comentarios"
name="comentarios"
rows="4"
maxlength="500"
placeholder="Write your comments here (max 500 characters)..."
></textarea>
<button type="submit">✅ Register</button>
</form>
</body>
</html>
Key validation attributes:
required— mandatory fieldminlength/maxlength— minimum/maximum text lengthmin/max— minimum/maximum numeric valuepattern— regular expression to validate the formatautocomplete— suggests to the browser what type of data to autofill
Variant 4: Form with fieldset, legend, and datalist
Long forms benefit from being organized into logical groups with <fieldset> and <legend>. Additionally, <datalist> offers suggestions as the user types.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<title>Form with 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>Travel Booking</h1>
<form>
<fieldset>
<legend>👤 Personal Information</legend>
<label for="nombre">Full name</label>
<input type="text" id="nombre" name="nombre" required />
<label for="email">Email</label>
<input type="email" id="email" name="email" required />
<label for="pais">Country of residence</label>
<input
type="text"
id="pais"
name="pais"
list="lista-paises"
placeholder="Type your country..."
/>
<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="United States" />
</datalist>
<p style="font-size:12px; color:#888; margin-top: 4px;">
Type the first few letters and select from the list.
</p>
</fieldset>
<fieldset>
<legend>✈️ Trip Details</legend>
<label for="destino">Destination (type your city)</label>
<input type="text" id="destino" name="destino" list="lista-destinos" placeholder="Type your destination..." />
<datalist id="lista-destinos">
<option value="Buenos Aires" />
<option value="Cancún" />
<option value="Madrid" />
<option value="New York" />
<option value="Paris" />
<option value="Rio de Janeiro" />
<option value="Rome" />
<option value="Tokyo" />
</datalist>
<label for="fecha-ida">Departure date</label>
<input type="date" id="fecha-ida" name="fecha-ida" required />
<label for="fecha-vuelta">Return date</label>
<input type="date" id="fecha-vuelta" name="fecha-vuelta" required />
<label for="pasajeros">Number of passengers</label>
<input type="number" id="pasajeros" name="pasajeros" min="1" max="10" value="1" />
<label for="clase">Class</label>
<select id="clase" name="clase">
<option value="economy">Economy</option>
<option value="premium">Premium Economy</option>
<option value="business">Business</option>
<option value="first">First Class</option>
</select>
</fieldset>
<div style="display: flex; gap: 12px;">
<button type="submit">🔍 Search Flights</button>
<button type="reset">🗑️ Clear</button>
</div>
</form>
</body>
</html>
<datalist> is an underrated HTML5 feature. It provides autocomplete suggestions without JavaScript, combining the best of a free <input> and a <select>.
Best Practices and Common Mistakes
| ✅ Best Practice | ❌ Common Mistake |
|---|---|
Always link <label for="..."> with the input's id | Use only placeholder as a label (disappears when typing) |
Use type="email", type="tel", type="url" as appropriate | Use type="text" for everything (lose validation and touch keyboards) |
Add required and min/max for native validation | Depend only on JavaScript for basic validations |
Organize long forms with <fieldset> and <legend> | Leave all fields in a single block without logical grouping |
Use autocomplete to improve user experience | Leaveautocomplete="off" on fields where the browser can help |
Use pattern with clear regular expressions | Create overly restrictive patterns that reject valid data |
Frequently Asked Questions (FAQ)
Do date, time, and number input types work in all browsers?
Yes, in all modern browsers (Chrome, Firefox, Safari, Edge since 2020). In very old browsers (IE11), these inputs degrade to type="text". For projects that must support IE11, you need a polyfill or a component library (React Datepicker, Flatpickr).
What's the difference between type="number" and type="tel"?
type="number" shows a numeric keypad with decimals and accepts min, max, and step attributes. type="tel" shows a telephone keypad (ideal for mobile) and doesn't enforce numeric restrictions, allowing characters like +, (, ), -, and spaces. Use number for quantities and tel for phone numbers.
Is HTML5 validation enough, or do I need JavaScript?
HTML5 validation covers 80% of cases (required fields, email format, numeric ranges). For more complex validations (e.g., "the return date must be after the departure date," "the username must not be in use"), you need JavaScript. The best strategy is to combine HTML5 validation (first line) + JavaScript (custom validations) + server-side validation (security).
Does <datalist> replace <select>?
No. <select> forces the user to choose an option from a closed list. <datalist> only suggests options; the user can type any value. Use <select> when options are fixed (e.g., country, month, category) and <datalist> when you want to suggest but allow freedom (e.g., city search, tags).
📘 Learn more about this topic here 👉 Creating HTML Forms.