Forms
Inputs, labels and validation without JavaScript.
Updated
What a form is
A form collects data from the user and sends it somewhere (a server, a function). It's the oldest interactive mechanism on the web and it works without JavaScript: the browser knows on its own how to gather the values and send them.
<form action="/subscribe" method="post">
<label for="email">Email</label>
<input id="email" name="email" type="email" required />
<button type="submit">Send</button>
</form>On submit, the browser builds a request with email=ana@x.com and sends it to /subscribe. In Next, action can be a Server Action directly.
The parts of a form
| Attribute / element | Role |
|---|---|
action |
where the data is sent |
method |
get (data in the URL — for searches) or post (in the body — for changes) |
name |
the key the value arrives under; without name, the field isn't sent |
<label for> |
the label linked to the input's id |
<button type="submit"> |
submits the form |
A <button> inside a form defaults to type="submit". Buttons that don't submit (open a modal, delete a row) get type="button".
Input types — and when to use them
| Type | When | Free bonus |
|---|---|---|
text |
short free text | — |
email |
email address | format validation, keyboard with @ on mobile |
password |
password | hidden characters, password manager |
number |
quantities | arrows, min/max/step |
tel |
phone | numeric keyboard on mobile (no validation) |
url |
link | format validation |
date, time |
date / time | native picker |
search |
search | clear button |
checkbox |
yes/no or several options | — |
radio |
a single option from a group (same name) |
arrow-key navigation |
file |
upload | accept="image/*" |
hidden |
a value that's sent but invisible (id, token) | — |
Other controls: <textarea> (long text), <select> + <option> (list), <fieldset> + <legend> (a group of related fields).
checkbox vs radio vs select: one choice out of 2–5 visible options → radio; one choice out of many → select; several choices → checkboxes.
Native validation
| Attribute | Effect |
|---|---|
required |
mandatory |
minlength / maxlength |
text length |
min / max / step |
numbers, dates |
pattern |
regular expression |
type |
the format (email, url) |
You style the state with :invalid, :valid, :user-invalid (only after the user has interacted).
Browser validation is for the user's convenience, not for security. Anyone can bypass it → always validate on the server too.
Reading the data in JS
form.addEventListener('submit', e => {
e.preventDefault()
const data = Object.fromEntries(new FormData(e.currentTarget))
})FormData reads every field with a name — the same object a Server Action receives. How to work with forms in React (controlled, React Hook Form, Zod) is in the Forms topic.
Common mistakes
- An input without
name→ the value disappears on submit. - An input without a
label(only aplaceholder) → inaccessible, and the hint disappears as you type. - Buttons without
typethat submit the form by accident. - Validation only on the client.
Summary
namedecides what gets sent;label for+idlinks the label.- The right input type = validation + the right keyboard, for free.
- Validate on the server too, always.