HTML Input Attributes
The <input> element is the most versatile tag in HTML forms, and almost all of its power comes from its attributes. The type attribute decides what kind of control appears, but a whole family of other attributes control the input’s default value, constraints, validation rules, and behavior. Understanding these attributes thoroughly is essential to building forms that collect clean, valid data without writing a single line of JavaScript.
Overview: How Input Attributes Work
An <input> element is a void element — it has no closing tag and no content between tags. Everything about how it looks and behaves is expressed through attributes on the opening tag itself, for example <input type="text" required>. When the browser parses this tag, it builds a single DOM node with a set of properties that mirror these attributes (e.g. value, required, disabled). The rendering engine then uses these properties to decide what widget to paint (a text box, a checkbox, a slider) and what constraints to enforce.
Attributes fall into a few broad categories:
- Identification attributes —
nameandid, which let the value be submitted and let a<label>connect to the field. - Default content attributes —
valueandplaceholder, which affect what the user initially sees. - Constraint attributes —
required,min,max,step,maxlength,minlength, andpattern, which the browser uses for built-in constraint validation before the form is allowed to submit. - State attributes —
disabledandreadonly, which change whether a field can be edited or submitted at all. - Behavioral hints —
autocomplete,autofocus, andlist(which links to a<datalist>).
Many of these are boolean attributes: their mere presence turns the feature on, and their absence turns it off. Writing disabled="disabled", disabled="", or simply disabled are all equivalent — the browser only checks whether the attribute exists in the markup, not what value it has. This trips up a lot of beginners who write disabled="false" expecting the field to be enabled — it is still disabled, because the attribute is still present.
Syntax
<input
type="text"
name="username"
id="username"
value=""
placeholder="Enter your username"
required
minlength="3"
maxlength="20"
autocomplete="username"
>
| Attribute | Purpose |
|---|---|
name |
The key used when the field’s value is submitted to the server. |
value |
The initial value shown when the page loads (or the current value, read via JavaScript). |
placeholder |
Faint hint text shown only when the field is empty; disappears on typing. Not a substitute for a label. |
required |
Boolean. Blocks form submission until the field has a value. |
disabled |
Boolean. Greys out the field, makes it unfocusable, and excludes its value from submission entirely. |
readonly |
Boolean. Field is visible and its value IS submitted, but the user cannot edit it. |
min / max |
Lower/upper bounds for numeric, date, and range-type inputs. |
step |
The increment allowed between valid values (used with min). |
maxlength / minlength |
Character count limits for text-like inputs. |
pattern |
A regular expression the value must match to be considered valid. |
autocomplete |
Hints the browser whether/how to offer autofill suggestions. |
autofocus |
Boolean. Automatically focuses this field when the page loads. |
list |
References the id of a <datalist> providing suggested values. |
Examples
Example 1: Basic constraints with required and placeholder
<form>
<label for="email">Email address</label>
<input type="email" id="email" name="email" placeholder="you@example.com" required>
<button type="submit">Sign up</button>
</form>
Result: A labeled email field displays faint grey text reading “you@example.com” until the user types. If the user clicks “Sign up” while the field is empty or contains text that isn’t a valid email shape, the browser blocks submission and shows a small validation bubble pointing at the field — no server round-trip needed.
This works because required and the built-in shape check for type="email" are part of HTML’s constraint validation API, which every modern browser implements natively.
Example 2: Numeric range with min, max, and step
<form>
<label for="qty">Quantity (1-10, even numbers only)</label>
<input type="number" id="qty" name="qty" min="0" max="10" step="2" value="2">
</form>
Result: A number spinner appears pre-filled with “2”, with up/down arrow controls. Clicking the up arrow jumps to 4, then 6, then 8, then 10 — it never lands on an odd number because step="2" starting from min="0" only allows even values. Typing “7” directly and submitting triggers a validation error because 7 doesn’t align with the step.
Example 3: A realistic signup field set
<form>
<label for="pwd">Password</label>
<input
type="password"
id="pwd"
name="pwd"
minlength="8"
maxlength="64"
pattern="(?=.*\d)(?=.*[a-zA-Z]).{8,}"
required
autocomplete="new-password"
>
<label for="referral">Referral code (optional)</label>
<input type="text" id="referral" name="referral" readonly value="PROMO2026">
<button type="submit">Create account</button>
</form>
Result: The password field masks typed characters as dots and refuses submission unless the value is at least 8 characters and matches the pattern (at least one digit and one letter). The referral field displays a locked-in value of “PROMO2026” that the user can see and that WILL be submitted with the form, but cannot edit or delete, because readonly (unlike disabled) still allows the value to be sent.
How It Works Step by Step
- The HTML parser reads the
<input>tag and its attributes, creating one DOM node with matching properties. - The rendering engine looks at
typeto choose the visual widget (text box, checkbox, slider, etc.), then applies the other attributes as modifiers to that widget. - While the user interacts with the field, the browser continuously checks it against any constraint attributes present (
required,pattern,min/max,minlength/maxlength) and updates the field’s internal validity state. - When the form is submitted, the browser runs constraint validation on every field. If any field is invalid, submission is cancelled, focus moves to the first invalid field, and a native error message bubble appears — before any network request is made.
- On successful submission, the browser collects
name=valuepairs from every field that is NOTdisabled— includingreadonlyfields — and encodes them into the request.
Common Mistakes
Mistake 1: Using placeholder instead of a label
<input type="text" name="city" placeholder="City">
This is wrong because the placeholder text vanishes the moment the user starts typing, leaving no visible cue for what the field is, and screen readers do not treat placeholder text as a reliable substitute for a real label. Use a <label> element for the persistent, accessible name, and reserve placeholder for a short example or hint:
<label for="city">City</label>
<input type="text" id="city" name="city" placeholder="e.g. Austin">
Mistake 2: Assuming disabled attribute submits its value
<input type="text" name="plan" value="Pro" disabled>
Because the field is disabled, the browser excludes it from the submitted form data entirely — the server never receives plan=Pro. If the value must reach the server but should not be user-editable, use readonly instead:
<input type="text" name="plan" value="Pro" readonly>
Mistake 3: Writing a boolean attribute with the wrong assumption
<input type="text" name="nickname" required="false">
Beginners expect this field to be optional, but boolean attributes in HTML only check for presence, not their string value — this field is still required. To make it optional, remove the attribute entirely:
<input type="text" name="nickname">
Best Practices
- Always pair an
<input>with a real<label>connected viafor/id— never rely onplaceholderalone. - Use the most specific
typeavailable (email,tel,number,date) so native validation and mobile keyboards work in your favor, then layer onrequired,min/max, orpatternas needed. - Set sensible
autocompletevalues (name,email,new-password,street-address) so browsers can autofill correctly and users can fill forms faster. - Prefer
readonlyoverdisabledwhenever the value should still be part of the submitted data. - Never rely on client-side attributes like
requiredorpatternas your only validation — always re-validate on the server, since HTML constraints can be bypassed. - Use
autofocussparingly and only on the single most important field, since it can be disorienting on pages with multiple forms or for screen reader users. - Keep visual styling (borders, colors, spacing) in CSS, not in the input’s attributes.
Practice Exercises
- Exercise 1: Build a labeled
<input type="text">for a “Coupon Code” field that only accepts exactly 6 uppercase letters or digits. Hint: you’ll need bothmaxlength/minlengthand apattern. - Exercise 2: Create a number field for “Age” that only allows values from 18 to 99, defaulting to 18.
- Exercise 3: Create two fields: one
readonlyfield showing a pre-filled account ID that should still be submitted, and onedisabledfield showing a legacy account ID that should never be submitted. Explain in a comment (outside the markup) which is which and why.
Summary
- Input attributes control identification (
name,id), default content (value,placeholder), constraints (required,min/max,step,minlength/maxlength,pattern), and state (disabled,readonly). - Boolean attributes are triggered by presence alone, not by their value —
disabled="false"is still disabled. disabledfields are excluded from form submission entirely;readonlyfields are still submitted but not editable.- Constraint attributes power the browser’s native validation, blocking submission and showing error bubbles before any data reaches the server.
placeholderis a temporary hint, not a replacement for a proper<label>.- Client-side constraints improve user experience but must always be backed up by server-side validation.
