Inputs, Labels and Choices
A form asks questions, and the answers come in different shapes: a name, an email address, a number, a date, one choice out of three. HTML has a field for almost every shape, and choosing the right one gives phones the right keyboard and screen readers the right description. One part of every field is never optional: the label, the visible words that say what the field is for.
On a printed questionnaire, every box has a question printed beside it, and the question stays there while you write. A box with faint grey writing inside it, which vanishes the moment your pen touches the paper, is not a question at all. That is the difference between a label and the placeholder text this page warns about.
Which Field for Which Answer?
Most fields are an input element, and its type attribute decides what kind. The default is text, for short free text. Then there are email, url for a web address, tel for a phone number, number for a quantity, date, password, which hides what is typed, and search. Each type changes up to three things: the keyboard a phone shows, the checks the browser makes before sending, and sometimes the control itself.
<label for="email">Email address</label> <input type="email" id="email" name="email"> <label for="phone">Phone number</label> <input type="tel" id="phone" name="phone"> <label for="start">Start date</label> <input type="date" id="start" name="start">
Put these three pairs inside a form and open the page. On a laptop the first two look like ordinary text boxes, and the third is split into day, month and year parts, with a small calendar to pick from. Open the same page on a phone and the differences grow: the email field brings up a keyboard with an at sign, the phone field brings up a number pad, and the date field opens the phone's own date picker.
Numbers are where beginners most often choose wrong. A number field is for quantities, things you might add up: tickets, years, grams. A phone number or a card number is not a quantity. A number field adds up and down arrows on a computer and will not accept the plus sign or the spaces a phone number often has. Use tel for phone numbers. For a card number, use a text field with inputmode="numeric", which asks phones for a number pad without changing anything else.
| Type | Phone keyboard | Built-in check |
|---|---|---|
| letters with an at sign | must look like an address | |
| number | numbers | must be a number |
| date | a date picker instead | must be a real date |
| tel | a phone keypad | none: phone formats vary too much |
Why Does Every Field Need a Label?
A label element holds the words that name a field. Its for attribute matches the field's id, and that match connects them. The connection does two things. Clicking the label moves the cursor into the field, which gives everyone a bigger target, and on a checkbox it ticks the box. And when a screen reader lands on the field, it reads the label's words as the field's name.
<!-- Placeholder only: not a label --> <input type="email" name="email" placeholder="Email address"> <!-- A label: always visible, always announced --> <label for="email">Email address</label> <input type="email" id="email" name="email">
Both fields look labelled before anyone types. The first uses placeholder, the faint grey text shown inside an empty field. It disappears the moment typing starts, so a visitor who looks back at the form no longer knows what the field was for. Its default grey is often too pale to read comfortably. And screen readers treat it inconsistently: some read it as the field's name, some read it late, some not at all.
The second field is announced the same way everywhere: the label's words followed by the kind of field, something like "Email address, edit text". A placeholder can still hold an example, such as a sample address, but only next to a real label, never instead of one.
DevTools shows what a screen reader will hear. In the Elements panel, select the input and open the Accessibility tab, one of the tabs beside Styles. The Name line shows the words a screen reader will use for the field, and where they came from. For the labelled field, it names the label.
Choices: Checkboxes, Radio Buttons and Lists
Some questions have a fixed set of answers. A checkbox lets the visitor pick any number of options, including none. A radio button lets them pick exactly one from a group. For both, the value attribute holds what is sent when the option is chosen.
<fieldset> <legend>How should I reply?</legend> <input type="radio" id="reply-email" name="reply" value="email" checked> <label for="reply-email">By email</label> <input type="radio" id="reply-phone" name="reply" value="phone"> <label for="reply-phone">By phone</label> </fieldset>
The browser draws a thin border around the group, with the question in its top edge, and two round buttons: By email, already chosen because of the checked attribute, and By phone. Choose By phone and By email clears itself. Submitted, the form sends one pair, reply equals phone. The fieldset element groups the options, and its legend is the group's question, which screen readers announce as the visitor moves into the group.
What makes the two buttons a group is the shared name. Give them different names and the browser treats them as two separate questions: both can be chosen, and neither can be unchosen. When radio buttons misbehave, compare their names first.
Two more fields complete the set. A select element is a drop-down list of option elements, useful when the choices are too many to show at once, such as a list of countries. A textarea is a box for several lines of text, such as a message.
autocomplete: Telling the Browser What a Field Is
The autocomplete attribute tells the browser what a field holds, using a fixed list of words: name, email, tel, street-address, new-password and many more. With that knowledge, the browser can offer the details the visitor has saved, and a password manager knows which field is which.
This is more than a convenience. For someone with a memory difficulty, or for whom every key press is effort, a form that fills itself in is the difference between finishing and giving up. The accessibility guidelines that Chapter 12 introduces ask for it on every field that collects information about the visitor, whenever one of the words on that list fits.
The Site's Contact Form
Here is the form for the site's contact.html, placed inside its main element under the page heading. It has three fields, named name, email and message, each with a label and, where one exists, an autocomplete word.
<form id="contact-form"> <label for="name">Your name</label> <input type="text" id="name" name="name" autocomplete="name"> <label for="email">Email address</label> <input type="email" id="email" name="email" autocomplete="email"> <label for="message">Message</label> <textarea id="message" name="message" rows="6"></textarea> <button type="submit">Send message</button> </form>
Labels and fields flow inline, so without CSS they run along one line like words in a sentence. The rule below turns the form into a flex column from Chapter 4, one item under another with a small gap. Form fields also ignore the page's font by default, and font: inherit makes them use it.
form {
display: flex;
flex-direction: column;
gap: var(--space-s);
max-width: 30rem;
}
input,
textarea,
button {
font: inherit;
}
Open contact.html through the preview server. The form is a column: each label above its field, the message box six lines tall, and the button at the bottom, all in the site's font. Click the words Email address and the cursor jumps into the email field. The form has no action yet, so sending it reloads the page with your words in the address. Topic 4 decides what it does instead.
- "Placeholder text is enough." It vanishes as soon as typing starts and is often too faint to read. Every field needs a real label.
- "A number field is right for phone and card numbers." Those are not quantities. Use
telfor phone numbers, and a text field withinputmode="numeric"for card numbers. - "Radio buttons need different names." A group shares one name, and that shared name is what makes the choices exclusive.
- The right types and real labels make a form usable on a phone and with a screen reader.
- The site's contact form now has its accessible markup, ready for checks and a script.
Knowledge Check
Why is a placeholder not a replacement for a label?
- It is never shown on phones or on small screens
- It is sent to the server in place of the value
- It disappears as soon as the visitor starts typing
- It stops the browser from checking the field
A form asks how many tickets a visitor wants. Which field fits best?
- An input with
type="number" - An input with
type="tel"for its keypad - Ten checkboxes, one for each amount
- A text input with a placeholder hint
Two radio buttons, By email and By phone, can both be chosen at once. What is the likely cause?
- They are not inside a
fieldsetelement - Their labels are missing the
forattribute - They share the same
valueattribute - They have two different
nameattributes
What does autocomplete="email" on a field do?
- It checks that the typed address really exists
- It tells the browser the field holds an email
- It fills in the site owner's address for them
- It sends the form once the field is filled in
You got correct