Forms and inputs: let visitors send something back
Until now your page only talks. A form lets it listen: an email address, a choice from a list, a box to tick. It's how a visitor gives something back.
The big idea
A form groups inputs with their labels and a submit button; attributes on each input control what it accepts.
See it in code
Every input needs a label. The label's for and the input's id must match, which ties them together:
<form class="space-y-2 p-6">
<label for="email" class="block text-sm font-medium text-slate-300">Email</label>
<input id="email" type="email" class="w-full rounded-lg border border-white/10 bg-white/5 px-4 py-2">
</form>Clicking the label puts the cursor in the field, because for="email" points at id="email". Screen readers use the same link to announce what the field is for.
Attributes shape an input's behavior. placeholder shows a hint, required refuses an empty submission, and focus: classes style the field while it's selected:
<form class="space-y-2 p-6">
<label for="email" class="block text-sm font-medium text-slate-300">Email</label>
<input id="email" type="email" required placeholder="you@example.com" class="w-full rounded-lg border border-white/10 bg-white/5 px-4 py-2 outline-none transition focus:border-violet-400 focus:ring-2 focus:ring-violet-500/40">
</form>type="email" makes the browser check for an address shape, and phones show a keyboard with an @ key. You got validation without writing any script.
A complete signup adds a dropdown, a checkbox wrapped in its own label, and a submit button. A form reads top to bottom and ends with its button:
<form class="mx-auto max-w-sm space-y-4 p-6">
<h2 class="text-2xl font-bold">Launch alerts</h2>
<div class="space-y-1">
<label for="alert-email" class="block text-sm font-medium text-slate-300">Email</label>
<input id="alert-email" type="email" required placeholder="you@example.com" class="w-full rounded-lg border border-white/10 bg-white/5 px-4 py-2 outline-none focus:border-violet-400">
</div>
<div class="space-y-1">
<label for="launches" class="block text-sm font-medium text-slate-300">Which launches?</label>
<select id="launches" class="w-full rounded-lg border border-white/10 bg-slate-900 px-4 py-2">
<option>All launches</option>
<option>Crewed missions</option>
<option>Mars missions</option>
</select>
</div>
<label class="flex items-center gap-2 text-sm text-slate-300">
<input type="checkbox"> Also send me image of the day
</label>
<button class="w-full rounded-full bg-gradient-to-r from-violet-600 to-fuchsia-600 px-6 py-3 font-semibold transition hover:opacity-90">Notify me</button>
</form>The checkbox sits inside its label, so no for or id is needed: clicking the words ticks the box. A button inside a form submits it by default.
Forms are how software collects structured input everywhere: a search box, a login, a checkout, a settings page. The label-plus-field pairing is the same in all of them.
Try it yourself
Add a fourth option to the dropdown. Then break the first example on purpose by changing for="email" to for="mail", and click the label to see what stops working.
The common mistake
A for that doesn't match its id. The form looks identical, but clicking the label does nothing and assistive technology can't name the field. The two values must match exactly.
What it unlocks
Form elements are configured almost entirely through attributes. To do something with what the visitor typed, you need a script that listens for events.