Chapter 27: Form Validation & Constraint Validation API

minlength and maxlength Validation

Enforcing String Length Boundaries: Mastering `tooShort`, `tooLong`, and the UTF-16 Code Point vs Grapheme Cluster Reality

LEARNING OBJECTIVES
  • Understand the distinct behavioral models of minlength (validation blocking) vs maxlength (input truncation).
  • Map length constraints to the validity.tooShort and validity.tooLong Constraint Validation API flags.
  • Recognize why an empty input field satisfies minlength unless explicitly combined with required.
  • Deconstruct Unicode string counting: UTF-16 code units vs code points vs extended grapheme clusters (emojis and ZWJ sequences).
  • Build a robust, accessible real-time character counter with aria-live state announcements.
🎬 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 writing a micro-essay for a competitive scholarship:

+-----------------------------------------------------------------------------+
|                        THE SCHOLARSHIP ESSAY ANALOGY                        |
+-----------------------------------------------------------------------------+
|                                                                             |
|   Rules: Minimum 50 words (minlength), Maximum 280 words (maxlength)        |
|                                                                             |
|   [Student Writes 20 words] ──► Allowed to type freely.                     |
|                                 Tries to submit: Professor rejects it!      |
|                                 ⚠️ "Too short! (tooShort = true)"           |
|                                                                             |
|   [Student Reaches 280 words] ─► The submission portal physically locks     |
|                                 the keyboard. Further typing is blocked!    |
|                                 🛑 Native input truncation                  |
|                                                                             |
|   [The Emoji Surprise 👨‍👩‍👧‍👦] ──► 1 visible family icon on screen,          |
|                                 but 11 UTF-16 code units under the hood!    |
|                                                                             |
+-----------------------------------------------------------------------------+
  1. maxlength is a Physical Barrier: As you type, once you hit the maximum character count, the browser physically stops accepting further keyboard input and truncates pasted content.
  2. minlength is an Evaluation Standard: The browser lets you type freely below the threshold. However, if you attempt to submit a non-empty string that has fewer characters than minlength, the browser halts submission and flags the input with tooShort = true.
  3. The Unicode Reality: The browser does not count characters the way human eyes see them (glyphs). It counts UTF-16 code units. A single colorful emoji like 👨‍👩‍👧‍👦 looks like 1 character to a human, but consumes 11 UTF-16 code units in the browser's engine!

Technical Deep Dive & Specifications

2.1 Enforcement Differences: minlength vs maxlength

According to the WHATWG HTML Standard (§ 4.10.5.3.5 & § 4.10.5.3.6):

Attribute User Typing Behavior Paste Behavior Submit Behavior API Validity Flag
minlength="N" Free typing allowed below $N$ Paste allowed below $N$ Blocks submit if $0 < \text{len} < N$ validity.tooShort
maxlength="N" Keyboard typing blocked at $N$ Paste truncated at $N$ Blocks submit if $\text{len} > N$ validity.tooLong
+----------------------------------------------------------------------------------------------------+
|                                    MINLENGTH / MAXLENGTH LIFECYCLE                                 |
+----------------------------------------------------------------------------------------------------+

 In HTML: <input type="text" minlength="5" maxlength="10">

 1. Initial State: value = ""
    • valueMissing = false (unless 'required' is present)
    • tooShort = false (Empty strings are EXEMPT from minlength!)

 2. User types: "abc" (length = 3)
    • tooShort = true (3 < 5)
    • Form submission is BLOCKED.

 3. User types: "abcdef" (length = 6)
    • tooShort = false, tooLong = false
    • Form submission is ALLOWED.

 4. User types: "abcdefghij" (length = 10)
    • Keyboard stops accepting keypresses (max reached).

 5. Programmatic Script sets: input.value = "abcdefghijklmnop" (length = 16)
    • tooLong = true (16 > 10)
    • Form submission is BLOCKED.

Important Rule: minlength only applies when the input is not empty. If a user leaves a minlength="5" optional field blank, it will submit without error. To require at least 5 characters and disallow empty submission, combine required and minlength="5".

2.2 The Unicode UTF-16 Code Unit Reality

The WHATWG specification explicitly mandates that length constraints are calculated using the string's UTF-16 code units (equivalent to JavaScript string.length), not human-perceived characters (Extended Grapheme Clusters).

+----------------------------------------------------------------------------------------------------+
|                                 HOW THE BROWSER COUNTS CHARACTERS                                  |
+----------------------------------------------------------------------------------------------------+

 Character / Glyph           Unicode Code Points                  UTF-16 Code Units (HTML length)
 ──────────────────────────────────────────────────────────────────────────────────────────────────
 'A'                         U+0041                               1 code unit   (length = 1)
 'é' (precomposed)           U+00E9                               1 code unit   (length = 1)
 'é' (decomposed e + ´)      U+0065 + U+0301                      2 code units  (length = 2)
 '😀' (Grinning Face)        U+1F600 (Surrogate Pair)             2 code units  (length = 2)
 '👨‍👩‍👧‍👦' (Family Emoji)       U+1F468 + U+200D + U+1F469 +        11 code units (length = 11)
                             U+200D + U+1F467 + U+200D + U+1F466

If your application has <input maxlength="10">, a user attempting to paste the family emoji 👨‍👩‍👧‍👦 (11 code units) will have the emoji completely rejected or broken in half because it exceeds the 10 code unit limit!

Modern JavaScript Solution: Intl.Segmenter

To count visible characters accurately for user interfaces:

// Grapheme-aware counting (Matches human eyes)
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
const countGraphemes = (str) => [...segmenter.segment(str)].length;

console.log(countGraphemes('👨‍👩‍👧‍👦')); // Returns 1 (Correct for humans!)
console.log('👨‍👩‍👧‍👦'.length);         // Returns 11 (HTML native UTF-16 count)

💻 Interactive Code Playground

Starter Code

The following microblog post publisher demonstrates minlength, maxlength, real-time visual progress, Unicode breakdown, and live validity flag inspection.

Line-by-Line Code Breakdown

  • Lines 82-90 (minlength="5" maxlength="40" required): Enforces that the title must contain at least 5 characters and truncates typing at 40 characters.
  • Lines 99-107 (minlength="20" maxlength="140" required): Sets textarea boundaries. If a user types 10 characters and clicks submit, the browser prevents submission with validity.tooShort = true.
  • Line 108 (aria-live="polite"): Ensures that as the character count updates, screen reader users receive periodic, non-intrusive character count announcements.
  • Lines 132-134 (Intl.Segmenter): Uses the modern internationalization API to split strings by user-perceived grapheme clusters, exposing the difference between native UTF-16 code units and visible characters.
  • Lines 147-156 (bValidity.tooShort, bValidity.tooLong): Real-time inspection of length validity flags.

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...
+---------------------------------------------------------------+
| Microblog Broadcast                                           |
| Enforcing minimum and maximum string boundaries.              |
|                                                               |
| Broadcast Title (5 – 40 Chars) *                              |
| [ Release v2.4 Announcement                                 ] |
| Min: 5 characters          24 / 40 UTF-16 (24 glyphs)         |
|                                                               |
| Broadcast Message (20 – 140 Chars) *                          |
| [ We are thrilled to launch our new constraint validation... ] |
| Min: 20 characters         58 / 140 UTF-16 (58 glyphs)        |
|                                                               |
| [ Publish Broadcast                                         ] |
|                                                               |
| [BODY VALIDITY STATE]                                         |
| • Native UTF-16 Length: 58 / 140                              |
| • Human Grapheme Count: 58                                    |
| • validity.tooShort: false                                    |
| • validity.tooLong: false                                     |
| • validity.valueMissing: false                                |
| • validity.valid: true                                        |
+---------------------------------------------------------------+

🏋️ Hands-On Exercise

🎯 The Challenge: Developer Bio & Security PIN Editor

Scenario: You are building an account security settings panel.

  • Security PIN: Must be exactly 6 characters (minlength="6" maxlength="6" inputmode="numeric" required).
  • Developer Biography: Must be between 30 and 250 characters (minlength="30" maxlength="250").
  • Character Counter: Implement a real-time counter displaying remaining characters for the biography ("X characters remaining").

Instructions:

  1. Write the HTML form with the security PIN and bio textarea controls.
  2. Apply minlength, maxlength, and required attributes.
  3. Write JavaScript to calculate and display remaining characters as the user types into the textarea.
  4. If remaining characters drop below 20, turn the counter text amber/warning.

🏁 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. Assuming minlength Blocks Empty Fields: If a field has minlength="10" but is NOT marked required, submitting an empty string "" will succeed because empty values are exempt from minlength. Always include required if the input cannot be omitted.
  2. Relying on maxlength for Backend Database Protection: An attacker using curl or modifying the DOM via DevTools can post a 50,000-character payload regardless of your maxlength attribute. Always validate string lengths on the server before database persistence.
  3. The Emoji Cutoff Bug: Emojis using Unicode Surrogate Pairs consume 2 UTF-16 code units. If maxlength="5" and the user types 4 ASCII letters ("test") and pastes an emoji ("😀"), the emoji will be rejected or truncated into an invalid surrogate fragment.

💡 Pro Tips

  1. Accurate Counting with Intl.Segmenter: For user-facing character counters, always count with Intl.Segmenter so compound emojis, flags, and accented characters are counted as single glyphs.
  2. Accessibility with aria-live="polite": When rendering dynamic character countdowns, mark the counter container with aria-live="polite" so screen readers announce remaining character milestones to visually impaired users without interrupting ongoing speech.

📌 Key Takeaways

  • maxlength Truncates: Physically prevents users from typing or pasting beyond the limit.
  • minlength Blocks Submit: Allows typing below the limit, but sets validity.tooShort = true during validation attempts.
  • Empty Exemption: An empty string does not trigger tooShort; pair minlength with required to enforce both presence and minimum length.
  • UTF-16 Code Units: HTML5 counts character lengths in UTF-16 code units (string.length), which can differ from human-perceived emojis.
  • validity.tooShort & validity.tooLong: The exact Constraint Validation API flags corresponding to length boundaries.
  • --
⭐ LEARN: HTML 🌟 ⚔️ QUIZ BATTLE ARENA // ACTIVE
3x
STREAK!
BONUS ACTIVE
COMBO
? Question 1 / 3

Why does an optional field with <input type="text" minlength="8"> successfully submit when the user leaves it completely blank?

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

What happens if a user types in an input with maxlength="10" and reaches 10 characters?

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

How many UTF-16 code units does a standard single surrogate-pair emoji like 😀 (U+1F600) consume in HTML5 maxlength calculations?

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