Labels & Text Inputs
Every text input needs a label that announces its purpose to screen readers and enlarges the click target for everyone. The type attribute tells the browser which virtual keyboard to show and which built-in validation to apply.
What it is
<label> connects a text description to a form control. The explicit association uses a for attribute on the label whose value matches the id of the input: <label for="email">Email address</label>. The implicit association wraps the input inside the label element directly. Both approaches tell the browser that clicking the label should focus the input and tell screen readers what to announce when the field receives focus.
<input> is a void element that covers a wide range of control types through its type attribute. For text collection: type="text" is the plain default; type="email" validates the value against an email format and shows an email-optimised keyboard on mobile; type="password" masks characters and prevents autocomplete from saving the value; type="tel" shows a phone dialpad on mobile but does not validate the format (phone number formats vary too much between countries for a universal pattern); type="number" shows a numeric keyboard; type="search" adds search semantics and often a clear button.
Why it matters
A label does two things that placeholder cannot: it persists when the user starts typing, and it is reliably announced by screen readers when the field receives focus. A placeholder disappears the moment a character is entered, leaving a user who paused mid-form with no reminder of what the field expected. Placeholder text also tends to fail contrast ratio requirements. Using placeholder as the sole label is one of the most common accessibility failures in web forms.
The type attribute is the lightest possible enhancement to a text input: it changes nothing visually on desktop but on a mobile device it switches the virtual keyboard to match the expected input. A phone number field with type="tel" shows a dialpad; an email field with type="email" shows @ on the primary keyboard row. These ergonomic improvements cost one attribute.
How it works
For explicit association, give the input a unique id and set the label's for to the same value. The two elements can be anywhere in the DOM relative to each other as long as the id is unique. For implicit association, place the input inside the <label> element with no for/id needed. Explicit is generally preferred: it keeps the label and input visually separable and works better with CSS grid layouts where the two elements are in different grid areas.
The autocomplete attribute hints to the browser which stored value to offer. Common values include name, email, current-password, new-password, tel, and street-address. Setting autocomplete="off" suppresses autofill for sensitive fields, but browsers may ignore it for known field types like passwords. The inputmode attribute goes a step further: it overrides the virtual keyboard independently of type. A PIN field styled as type="text" with inputmode="numeric" shows a number pad without triggering the number input's stepper controls.
Every input in a form that is not decorative needs a programmatic label. If a visual design places the label away from the input or uses an icon instead of text, use aria-label (a string directly on the input) or aria-labelledby (pointing to an element by id) to supply the accessible name. These are fallbacks; a real <label> is always preferable.
Try it
Click the label text to see the input focus activate. Compare the associated pair with a placeholder-only field.
<!-- explicit association: for + id --><label for="email"> Email address</label><input id="email" name="email" type="email" autocomplete="email" placeholder="you@example.com"/> <!-- placeholder is NOT a label --><input type="text" placeholder="Full name"/> <!-- type controls keyboard + validation --><input type="text" /><input type="email" /><input type="password" /><input type="tel" /><input type="number" />
Label + input association
Clicking the label text focuses the input. The for attribute on the label must match the input's id.
Placeholder is not a label
type controls keyboard + validation
type="text"plain text, any valuetype="email"validates format, @ keyboardtype="password"masked characterstype="tel"dialpad keyboard, no validationtype="number"numeric keyboard, stepperstype="url"validates URL, .com keyboardCheck yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Always pair a
<label>with every input:foron the label must match theidon the input for explicit association. placeholderis not a label: it disappears when the user types and is not reliably announced by screen readers.type="tel"shows a phone dialpad but does not validate the number format.autocompleteandtypetogether enable one-tap autofill and password manager integration.
Done with this concept?
Mark it complete to track your progress. No login needed.