Learning on Web Dev Open is free for all.

Take It Apart > HTML is a data structureForms that behave before any JavaScript
Phase 01HTML is a data structure40 of 434

Forms that behave before any JavaScript

Required, type, pattern, min, autocomplete, inputmode. Six attributes that replace a validation library and a week of your life.

Build30 minAI adversary

A form built from the right attributes validates before a single line of your code runs, in every browser, including on the slow phone where your bundle has not finished downloading. This is not a fallback, it is the primary mechanism, and the JavaScript is the enhancement.

Work through the instrument below first. Toggle each attribute on and off and watch three things change: the field’s validity state, the browser’s own error message, and, for inputmode and autocomplete, which keyboard a phone user gets. That last one is invisible on a laptop and enormous on a phone: inputmode="numeric" on a postcode field is the difference between a number pad and hunting through a QWERTY keyboard.

What the attributes already do

JavaScript budget: 0 lines
autofillone tap: the address the browser already has

Nothing has been submitted. The submit handler calls preventDefault and reports checkValidity() instead.

Attributes: switch one off

An empty field blocks submission and reports valueMissing before anything is sent.

typeMismatch on anything that is not an address, plus an email keyboard on a phone and the browser's saved addresses.

patternMismatch as the user types, with no listener attached.

tooShort, and a browser message that names the count the user is missing.

rangeUnderflow and rangeOverflow, plus stepper buttons that stop at the bounds.

The browser and the password manager know what this field is, and fill it in one tap from saved data.

A phone keypad instead of a full keyboard on every touch device.

Live validity: read off the elements
Email addressvalid

validationMessage: empty

Handlevalid

validationMessage: empty

Seatsvalid

validationMessage: empty

Phonevalid

validationMessage: empty

The keyboard this field opens: Email address

The @ and the full stop move onto the main row. No space bar hunt.

Focus a different field to see which keyboard it opens. None of this is visible on a desktop, and most of your users are not on one.

JavaScript budget
0lines you would write to get back what is switched off
  • Everything is on. The form validates, names its own errors in the user’s language, opens the right keyboard and offers autofill, with no script.

Zero lines. Required fields, address checking, a pattern, a range, autofill and the right keyboard: all of it declared in the markup, all of it working before a single script has loaded, and all of it still working if the script never arrives.

The messages above are your browser’s, in your browser’s language: the wording differs between Chrome, Firefox and Safari, which is why you never hard-code a comparison against them. Native validation is the floor, not the ceiling: for anything the constraint attributes cannot express, setCustomValidity keeps your rule inside the same machinery.

Switch the attributes on and off. The JavaScript budget counter is the useful measure of what each one saves you.

Then build one yourself. Make a sign-up form with: a name field that is required and has autocomplete="name"; an email field with type="email" and autocomplete="email"; a password with minlength and autocomplete="new-password"; a postcode with inputmode set appropriately for your country and a pattern that matches it; and a date of birth with type="date" and a max that makes someone born tomorrow impossible.

Submit it with everything empty. Read the browser’s own error messages. They are translated into the user’s language, positioned by the browser, and announced by screen readers, and you wrote none of it.

Now add exactly as much JavaScript as improves it and no more: use setCustomValidity to replace one message with a better one, and :user-invalid in CSS to style fields red only after the user has actually interacted with them rather than on page load. That second one is the detail that separates a form that feels helpful from one that feels accusatory.

The autocomplete attribute deserves one more paragraph because it is the most under-used attribute in HTML. With the right token, a browser fills a whole address from a saved profile, a password manager offers the correct credentials, and a phone offers the one-time code from a text message. Without it, the user types everything. The tokens are a fixed published list, look up the right one rather than guessing, because autocomplete="email" works and autocomplete="userEmail" silently does nothing.

Done when

  • A form with at least five fields that validates fully with JavaScript disabled
  • Correct type, inputmode and autocomplete on every field where one applies
  • One custom validation message set through setCustomValidity
  • Invalid styling that appears only after interaction, not on load
  • Tested once with the network throttled and scripts blocked, and still usable

Nobody marks this for you. It goes into your phase checkpoint, where a person does.

Build this in your own editor

This one runs on your machine rather than in the browser workbench. Work to the outcomes below, then come back and mark it complete.

Worth reading

You should now be able to

  • Build a form that validates correctly with zero JavaScript
  • Choose the right input type and inputmode for a field
  • Explain what autocomplete does for a user on a phone
  • Read the constraint validation API and use it for custom messages
Ask the community

Loading…