AniUI Academy

Forms and Inputs

form, label, input types, select, textarea and button — how to collect input correctly, associate labels with controls, and avoid the common button-type gotcha.

9 min read

Forms are how a page collects information from a visitor — a search box, a login, a checkout. This lesson covers the elements involved and a few gotchas that catch people who learn forms informally.

<form> and its two key attributes

<form action="/submit" method="post">
  <!-- inputs go here -->
</form>
  • action — the URL the form's data gets sent to when submitted.
  • method — usually get or post. get appends the data to the URL as a query string (fine for something like a search form, since the result can be bookmarked or shared); post sends it in the request body instead, the right choice for anything that changes data or shouldn't be visible in the URL, like a login form.

<label> — the two correct ways to associate it

A label needs to be programmatically tied to its control, not just placed visually near it, or a screen reader has no way to know they belong together. There are two valid ways to do this:

1. Matching for and id:

<label for="email">Email address</label>
<input type="email" id="email" name="email" />

2. Wrapping the input inside the label:

<label>
  Email address
  <input type="email" name="email" />
</label>

Both are equally valid and create a real association — clicking the label text focuses the input either way, and a screen reader announces the label when the input receives focus. Pick whichever fits your markup better; the for/id version is more common when the input needs to sit somewhere the label can't directly wrap.

placeholder is not a label

<!-- Wrong: no real label -->
<input type="email" placeholder="Email address" />
 
<!-- Right: a real label, placeholder optional on top -->
<label for="email">Email address</label>
<input type="email" id="email" placeholder="you@example.com" />

placeholder shows hint text inside an empty field, and it vanishes the moment the visitor starts typing — at which point, without a real label, the field's purpose disappears from view entirely. It's also not consistently announced by assistive technology the same reliable way a proper <label> is. Use placeholder for a short example of the expected format, on top of a real label — never as a replacement for one.

<input> and its common types

<input type="text" />
<input type="email" />
<input type="password" />
<input type="number" />
<input type="checkbox" />
<input type="radio" />
<input type="date" />
  • text — plain single-line text, the default if type is omitted.
  • email — behaves like text, but mobile browsers show an @-friendly keyboard, and the browser can validate it looks like an email address on submit (more on validation next lesson).
  • password — masks the typed characters.
  • number — restricts input to numeric values and typically shows increment/decrement controls.
  • checkbox — an independent on/off toggle. Multiple checkboxes with the same name let a visitor pick any number of options.
  • radio — one choice from a group. Radios sharing the same name attribute become mutually exclusive — checking one unchecks the others in that group.
  • date — a native date picker.
<label>
  <input type="radio" name="plan" value="basic" /> Basic
</label>
<label>
  <input type="radio" name="plan" value="pro" /> Pro
</label>

Notice both radios share name="plan" — that shared name is what groups them together as mutually exclusive.

<select> and <option>

<label for="country">Country</label>
<select id="country" name="country">
  <option value="us">United States</option>
  <option value="ca">Canada</option>
  <option value="uk">United Kingdom</option>
</select>

<select> renders a dropdown; each <option> is one choice. value is what gets submitted; the text between the tags is what the visitor sees.

<textarea>

<label for="message">Message</label>
<textarea id="message" name="message" rows="4"></textarea>

For multi-line free text. Unlike <input>, its default content goes between the opening and closing tags, not in a value attribute. rows sets a starting visible height (the visitor can typically still resize it).

<button> and its types — the real gotcha

<button type="submit">Submit</button>
<button type="button">Cancel</button>
<button type="reset">Reset</button>
  • submit — submits the enclosing form.
  • button — does nothing on its own; used when you're attaching custom JavaScript behaviour instead of a form submission.
  • reset — clears the form back to its default values. Rarely what you actually want on a real form; easy to click by accident and lose everything typed.

The gotcha: a <button> placed inside a <form> with no type attribute set defaults to type="submit". This surprises people constantly — add what you thought was a harmless "Cancel" or icon button inside a form, forget to set type="button", and clicking it submits the whole form unexpectedly. If a button inside a form isn't meant to submit it, you must set type="button" explicitly — the browser will not infer that for you.

Try it yourself

Try it yourself
Loading playground...

What to remember

  • Associate every <label> with its control via matching for/id, or by wrapping the control inside the label.
  • placeholder is a hint on top of a label, never a replacement for one — it disappears once typing starts.
  • Radios sharing a name become mutually exclusive; checkboxes are independent toggles.
  • A <button> inside a <form> defaults to type="submit" — set type="button" explicitly for anything that shouldn't submit.

Check yourself

3 questions · pass 3/3 to unlock Form Validation

up to 50
  1. 1.What are the two valid ways to associate a <label> with its input?

  2. 2.A <button> with no type attribute, placed inside a <form>, will:

  3. 3.Why is placeholder not a substitute for <label>?

3 left to answer