Chapter 27: Form Validation & Constraint Validation API

min, max, and step Range Validation

Enforcing Numerical and Temporal Bounds: Mastering `rangeUnderflow`, `rangeOverflow`, and `stepMismatch`

LEARNING OBJECTIVES
  • Understand the mathematical mechanics of min, max, and step attributes across numerical and temporal inputs.
  • Map range attributes directly to the validity.rangeUnderflow, validity.rangeOverflow, and validity.stepMismatch API flags.
  • Master the step-base algorithm to understand why min="3" step="5" permits 8 and 13, but rejects 10.
  • Implement step="any" to permit arbitrary floating-point numbers without triggering step mismatch errors.
  • Enforce business boundaries on temporal inputs (date, time, datetime-local).
🎬 INTERACTIVE VISUAL PIPELINE Core Architecture Simulation
🌐
1. Input
Directives & Tags
⚙️
2. Parse
Tokenizer & AST
🌳
3. Layout
Box Model & Flow
🎨
4. Render
GPU Paint & Composite
PHASE 1: INPUT & DIRECTIVES
Browser receives declarative markup stream, parsing tag tokens and initializing component state.

📖 The Mental Model & Story (Intuitive Foundation)

Imagine stepping across a river using a series of evenly spaced stones, alongside a strict bridge weight capacity:

+-----------------------------------------------------------------------------+
|                          THE STEPPING STONES ANALOGY                        |
+-----------------------------------------------------------------------------+
|                                                                             |
|      River Bank (min = 3)                                River Bank (max = 18)
|           │                                                       │         |
|           ▼                                                       ▼         |
|         [ 3 ] ──────► [ 8 ] ──────► [ 13 ] ──────► [ 18 ] ───► (Bridge End) |
|                     ▲          ▲                                            |
|                     │          │                                            |
|          Step Size (+5)        │                                            |
|                                │                                            |
|                         Attempt: 10                                         |
|                         (Splashes in Water! stepMismatch = true)            |
|                                                                             |
|   Attempt: 1 (Too low! rangeUnderflow)  Attempt: 25 (Too high! rangeOverflow)
|                                                                             |
+-----------------------------------------------------------------------------+
  1. The Minimum Boundary (min): You cannot step behind the starting bank. If you try to stand at position 1, you fall backward (rangeUnderflow).
  2. The Maximum Boundary (max): The path ends at position 18. Trying to step to position 25 exceeds the limit (rangeOverflow).
  3. The Step Interval (step): The stones are placed at intervals of 5 starting from position 3. You can only land safely on 3, 8, 13, and 18. If you try to step on position 10, you step into empty water (stepMismatch).

In HTML5, inputs of type number, range, date, time, and datetime-local use this exact stepping stone algorithm.


Technical Deep Dive & Specifications

2.1 The Step-Base Calculation Algorithm

According to the WHATWG HTML Standard (§ 4.10.5.3.8 "The step attribute"), an input value is valid with respect to step if and only if:

$$\text{Value is a valid step} \iff (\text{value} - \text{stepBase}) \pmod{\text{step}} = 0$$

What is stepBase?

  • If the element has a min attribute, $\text{stepBase} = \text{min}$.
  • If the element has no min attribute, but has a value attribute default, $\text{stepBase} = \text{defaultValue}$.
  • Otherwise, $\text{stepBase} = \text{defaultStepBase}$ (which is 0 for numbers).
Example: <input type="number" min="10" max="50" step="10">
• Valid values: 10, 20, 30, 40, 50
• Invalid values: 15 (stepMismatch), 5 (rangeUnderflow), 60 (rangeOverflow)

Example: <input type="number" min="3" max="23" step="5">
• Valid values: 3, 8, 13, 18, 23 (Notice: 5, 10, 15 are INVALID because base is 3!)

2.2 The step="any" Escape Hatch

By default, <input type="number"> has an implicit step="1". If a user enters 4.25, the browser rejects the input with a stepMismatch error!

To allow arbitrary decimal values (such as currency fractions, latitude/longitude, or physics measurements) while still retaining min and max constraints, use step="any":

<!-- Allows ANY floating-point number between 0.0 and 100.0 -->
<input type="number" min="0" max="100" step="any">

2.3 Constraint Validation Flags

The Constraint Validation API exposes three specific boolean flags on element.validity for range checking:

+----------------------------------------------------------------------------------------------------+
|                                    RANGE VALIDITY FLAGS MATRIX                                     |
+----------------------------------------------------------------------------------------------------+

 FLAG                  TRIGGER CONDITION                              HTML ATTRIBUTE
 ───────────────────────────────────────────────────────────────────────────────────────────────────
 validity.rangeUnderflow   Parsed value is strictly less than min       min="value"
 validity.rangeOverflow    Parsed value is strictly greater than max    max="value"
 validity.stepMismatch     (value - stepBase) is not a multiple of step step="value"

2.4 Temporal Input Boundaries (date, time, datetime-local)

Range validation is not limited to integers and floats. Temporal inputs use ISO 8601 strings:

Input Type Format Example step Unit Example Usage
<input type="date"> YYYY-MM-DD Days (1 = 1 day) min="2026-01-01" max="2026-12-31"
<input type="time"> HH:MM or HH:MM:SS Seconds (900 = 15 mins) min="09:00" max="17:00" step="900"
<input type="month"> YYYY-MM Months (1 = 1 month) min="2026-01" max="2026-12"
<input type="datetime-local"> YYYY-MM-DDTHH:MM Seconds (3600 = 1 hour) min="2026-08-01T00:00"

SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
HTML STARSHIP CODE TERMINAL example.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45°C
INSPECTING DOM: VALID
TAGS: SCANNING...

💻 Interactive Code Playground

Starter Code

The following financial transaction dashboard demonstrates min, max, and step across currency amounts, transaction dates, and appointment booking time slots.

Line-by-Line Code Breakdown

  • Lines 82-90 (min="10.00" max="10000.00" step="0.01"): Restricts numeric input to financial amounts. Entering 9.99 triggers rangeUnderflow, entering 10000.01 triggers rangeOverflow, and entering 50.123 triggers stepMismatch.
  • Lines 97-105 (<input type="date" min="2026-07-01" max="2026-12-31">): Enforces date boundaries using ISO-8601 strings (YYYY-MM-DD).
  • Lines 111-119 (<input type="time" min="09:00" max="17:00" step="900">): Sets a time window between 9 AM and 5 PM. step="900" enforces 15-minute granularity (900 seconds). Entering 09:07 triggers stepMismatch.
  • Lines 141-150 (v.rangeUnderflow, v.rangeOverflow, v.stepMismatch): Inspects all three individual flags from the validity object.

Expected Browser Render Output


SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
HTML STARSHIP CODE TERMINAL playground.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45°C
INSPECTING DOM: VALID
TAGS: SCANNING...
+---------------------------------------------------------------+
| Treasury Transfer Portal                                      |
| Enforcing strict numerical and temporal bounds.               |
|                                                               |
| Transfer Amount ($10.00 – $10,000.00) *                       |
| [ 500.00                                                    ] |
| min="10.00" max="10000.00" step="0.01"                       |
|                                                               |
| Execution Date (2026-07-01 to 2026-12-31) *                  |
| [ 2026-08-21                                                ] |
| min="2026-07-01" max="2026-12-31" step="1" (daily)           |
|                                                               |
| Settlement Time Slot (09:00 – 17:00, 15m intervals) *         |
| [ 09:15                                                     ] |
| min="09:00" max="17:00" step="900" (900s = 15 minutes)        |
|                                                               |
| [ Execute Wire Transfer                                     ] |
|                                                               |
| [AMOUNT] Real-time Validity:                                  |
| • Value: "500.00"                                             |
| • rangeUnderflow: false                                       |
| • rangeOverflow: false                                        |
| • stepMismatch: false                                         |
| • valid: true                                                 |
+---------------------------------------------------------------+

🏋️ Hands-On Exercise

🎯 The Challenge: Real Estate Auction Bidding Terminal

Scenario: You are building an auction bidding module for real estate properties.

  • Starting Price (min): $250,000
  • Maximum Reserve Ceiling (max): $2,000,000
  • Bid Increment (step): Bids must increase in exact increments of $5,000.
  • Auction Slot Time: Bidding is only open between 10:00 and 16:00, in increments of 30 minutes (1800 seconds).

Instructions:

  1. Create a form with a number input for bidAmount and a time input for biddingTime.
  2. Configure min, max, and step on both inputs according to the rules above.
  3. Test that entering $255,000 is valid, but $252,500 triggers stepMismatch.
  4. Test that 10:30 is valid, but 10:15 triggers stepMismatch.

🏁 Starter Code Sandbox

SYS: ACTIVE
HULL: 98%
CORE: STABLE
NET: ONLINE
STARTER CODE SANDBOX exercise.html
LIVE RENDER & DIAGNOSTICS CORE TEMP: 45°C
INSPECTING DOM: VALID
TAGS: SCANNING...

⚠️ Common Pitfalls

  1. Default step="1" on Numbers: Leaving off the step attribute when asking for decimal numbers (e.g. $19.99 or GPS coordinates 37.7749). The browser defaults step to 1 on numbers, causing valid decimals to be rejected with stepMismatch. Always specify step="0.01" or step="any".
  2. Forgetting Step-Base Offsets: Writing <input type="number" min="1" step="2"> and expecting even numbers (2, 4, 6) to be valid. The step base is 1, so only odd numbers (1, 3, 5, 7) are valid!
  3. Time Inputs and Seconds Precision: The default step for <input type="time"> is 60 (one minute). If your users need to specify seconds (10:15:30), you must specify step="1".

💡 Pro Tips

  1. Dynamic Date Min/Max Boundaries: In booking applications, restrict checkout dates to future days dynamically via JavaScript:
    const today = new Date().toISOString().split('T')[0];
    document.getElementById('checkin').min = today;
    
  2. Use step="any" for Unrestricted Floats: When building forms for geographical coordinates (latitude/longitude) or scientific measurements, step="any" eliminates step checks completely while keeping min and max constraints active.

📌 Key Takeaways

  • rangeUnderflow: Occurs when the input value is strictly less than the min attribute.
  • rangeOverflow: Occurs when the input value is strictly greater than the max attribute.
  • stepMismatch: Occurs when $(value - stepBase) \pmod{step} \neq 0$.
  • Step Base: Defaults to min if defined, otherwise 0 for numbers. Step calculations are always relative to the base.
  • step="any": Allows any floating-point number without triggering stepMismatch.
  • Temporal Steps: For <input type="time">, step values are measured in seconds (900 = 15 minutes, 1 = 1 second).
  • --
⭐ LEARN: HTML 🌟 ⚔️ QUIZ BATTLE ARENA // ACTIVE
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 1 / 3

Given the element <input type="number" min="5" step="3">, which of the following values is VALID?

Question 1 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 2 / 3

Why does an <input type="number"> without a step attribute show a validation error when a user inputs 12.50?

Question 2 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 3 / 3

How do you configure an <input type="time"> to allow appointment selection strictly in 15-minute increments?

Question 3 / 3 Topic: HTML Fundamentals
00:45 REMAINING
XP REWARD
+250 XP