Form and Input Controls

A <form> groups controls whose values are sent together: <input> (<input> and Its Types), <button>, <select> with <option> and <optgroup>, <textarea> and <output> (<output>). <fieldset>, <legend> and <label> give them structure and names. On <form>, action is the URL that receives the data (default: the current page), method is get (values in the query string), post (values in the body) or dialog (just close the enclosing <dialog>), enctype picks the body encoding, target where the response appears (_self, _blank, a frame name), and novalidate turns off validation.

Use get for searches and filters (the result can be bookmarked) and post for anything that changes data. File uploads need method="post" with enctype="multipart/form-data"; with the default encoding the browser sends only the file name. autocomplete sets the default for autofill (Validation and Autofill), and accept-charset now allows only UTF-8.

Structure: fieldset, legend and label

<fieldset> groups related controls in a box captioned by its first child, <legend>, which screen readers announce with the controls inside. <fieldset disabled> disables every control inside (except within the legend), and disabled controls are not submitted.

Every control needs a <label>: point for at the control's id, or wrap the control inside the label. Clicking the label focuses or toggles the control, and its text becomes the control's accessible name. A placeholder is not a label: it disappears as soon as the user types.

button, select and textarea

<button> can contain markup. Its type defaults to submit, so write type="button" for script-driven buttons such as "Show password". A submit button can override the form with formaction, formmethod, formenctype, formnovalidate and formtarget, and its own name/value pair is sent, so "Save draft" and "Publish" buttons can share one form.

<select> shows a drop-down; multiple allows several choices and size shows that many rows as a list box. <option> has value (defaulting to its text), selected, disabled and label; <optgroup label> adds group headings. <textarea> takes its initial value between its tags; rows and cols set its size, and wrap="hard" (with cols) submits line breaks where the text wrapped on screen.

A support request form with select, textarea and buttonsHTMLLive
<style>
  body { font: 15px/1.4 system-ui, sans-serif; margin: 12px; }
  fieldset { border: 1px solid #9ab; border-radius: 8px; margin: 0 0 10px; }
  legend { font-weight: 600; padding: 0 4px; }
  label { display: block; margin: 4px 0; }
  select, textarea { font: inherit; width: 100%; box-sizing: border-box; }
  button { font: inherit; padding: 4px 12px; margin-right: 6px; }
</style>
<form id="ticket" action="/tickets" method="post">
  <fieldset>
    <legend>Your request</legend>
    <label>Product
      <select name="product">
        <optgroup label="Software">
          <option value="ide">Code editor</option>
          <option value="cli" selected>Command-line tools</option>
        </optgroup>
        <optgroup label="Hardware">
          <option value="mon" disabled>Monitor (discontinued)</option>
        </optgroup>
      </select>
    </label>
    <label>Affected versions
      <select name="versions" multiple size="2">
        <option selected>4.1</option><option selected>4.2</option></select></label>
    <label>Problem
      <textarea name="details" rows="3" required>Steps to reproduce:
1. </textarea></label>
  </fieldset>
</form>
<button form="ticket" name="intent" value="send">Send request</button>
<button form="ticket" name="intent" value="draft" formnovalidate>Save draft</button>
<button form="ticket" type="reset">Reset</button>
Browser output of Listing 2.26
Browser output of 26

The buttons sit outside the <form> but belong to it through form="ticket". "Save draft" sends intent=draft and skips validation; the server sees versions=4.1&versions=4.2, one pair per selected option. Avoid control names such as action or submit: form.action would return the control instead of the URL, and form.submit() would stop being a function.

Practical Advice