05Lezione

Form HTML

Input, validazione nativa, accessibilità e stile dei moduli web. I form sono il principale punto di interazione tra utente e server.

L'Elemento Form

<form> è il contenitore per tutti gli elementi che raccolgono dati. Due attributi fondamentali: action (dove inviare i dati) emethod (come inviarli — GET o POST).

html
<form action="/submit" method="POST">
  <!-- elementi del form qui -->
  <button type="submit">Submit</button>
</form>
GET vs POST

GET: i dati appaiono nell'URL (?q=search). Usa per ricerche e filtri — il risultato è linkabile. POST: i dati vanno nel body HTTP. Usa per login, registrazioni e acquisti — più sicuro per dati sensibili.

Input e Tipi

<input> è l'elemento più versatile dei form. L'attributotype ne definisce comportamento, validazione automatica e tastiera mobile.

type="text"

Free text — default

type="email"

Validates email format

type="password"

Hidden text

type="number"

Numbers only

type="tel"

Phone number

type="url"

Validates URL format

type="search"

Search field with ×

type="date"

Native date picker

type="time"

Native time picker

type="color"

Color picker

type="range"

Min/max slider

type="file"

File upload

type="checkbox"

Multiple selection

type="radio"

Single selection

type="hidden"

Hidden field

html
<!-- Attributi comuni -->
<input type="text"     name="username"  placeholder="John Doe">
<input type="email"    name="email"     placeholder="john@example.com">
<input type="password" name="password"  minlength="8">
<input type="number"   name="age"       min="18" max="99">
<input type="date"     name="birthdate" min="1900-01-01">
<input type="range"    name="volume"    min="0" max="100" step="5">
<input type="color"    name="color"     value="#0EA5E9">

Label e Accessibilità

Ogni input deve avere una <label> associata. È fondamentale per l'accessibilità: gli screen reader annunciano il campo, e cliccando sulla label il focus va direttamente all'input.

html
<!-- METODO 1: for/id — raccomandato -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">

<!-- METODO 2: wrapper — alternativa valida -->
<label>
  Email address
  <input type="email" name="email">
</label>

<!-- ❌ SBAGLIATO: il placeholder non è una label -->
<input type="email" placeholder="email@example.com">
<!-- nessuna label = inaccessibile! -->
Placeholder ≠ Label

Il placeholder scompare non appena l'utente inizia a digitare — non usarlo mai come sostituto della label. È solo un suggerimento opzionale, non un'etichetta permanente.

Fieldset e Legend

<fieldset> raggruppa campi correlati. <legend>fornisce un titolo al gruppo, annunciato dagli screen reader come contesto per tutti i campi interni.

html
<form>
  <fieldset>
    <legend>Personal information</legend>

    <label for="first-name">First name</label>
    <input type="text" id="first-name" name="first-name">

    <label for="last-name">Last name</label>
    <input type="text" id="last-name" name="last-name">
  </fieldset>

  <fieldset>
    <legend>Preferred contact method</legend>

    <label>
      <input type="radio" name="contact" value="email"> Email
    </label>
    <label>
      <input type="radio" name="contact" value="phone"> Phone
    </label>
  </fieldset>
</form>

Select, Textarea, Checkbox e Radio

html
<!-- SELECT: menu a tendina con gruppi opzionali -->
<select name="country" id="country">
  <optgroup label="Europe">
    <option value="it">Italy</option>
    <option value="ch">Switzerland</option>
  </optgroup>
  <optgroup label="America">
    <option value="us">United States</option>
  </optgroup>
</select>

<!-- TEXTAREA: testo su più righe -->
<textarea name="bio" id="bio" rows="5"
          placeholder="Tell us about yourself..."></textarea>

<!-- CHECKBOX: selezione multipla (name diversi) -->
<label><input type="checkbox" name="css" value="css"> CSS</label>
<label><input type="checkbox" name="js"  value="js"> JavaScript</label>

<!-- RADIO: selezione singola (STESSO name) -->
<label><input type="radio" name="level" value="beginner">    Beginner</label>
<label><input type="radio" name="level" value="intermediate"> Intermediate</label>
<label><input type="radio" name="level" value="advanced">    Advanced</label>
L'attributo name

name identifica il campo nel form inviato. I radio button con lo stessoname formano un gruppo esclusivo — uno solo può essere selezionato.

Validazione HTML5

HTML5 offre validazione nativa senza JavaScript. Il browser controlla i campi prima dell'invio e mostra messaggi di errore nella lingua del sistema.

html
<!-- Attributi di validazione -->
<input type="text"   name="username" required>
<input type="email"  name="email"    required>
<input type="text"   name="username" minlength="3" maxlength="20">
<input type="number" name="age"      min="18" max="99">
<input type="text"   name="zip"      pattern="[0-9]{5}" title="5 digits">
<input type="url"    name="website"  required>
css
/* Pseudo-classi per feedback visivo */
input:valid   { border-color: #22c55e; }
input:invalid { border-color: #ef4444; }

/* Solo dopo l'interazione dell'utente (browser moderni) */
input:user-valid   { border-color: #22c55e; }
input:user-invalid { border-color: #ef4444; }

/* Campi obbligatori */
input:required { border-left: 3px solid #0EA5E9; }
Client-side validation ≠ security

La validazione HTML5 migliora l'UX ma non è sicurezza. Chiunque può bypassarla modificando il DOM. Valida sempre i dati anche lato server.

Stilizzare i Form

I form hanno stili di default che variano tra browser. Una reset di base li rende coerenti e controllabili da CSS.

css
/* Reset base per tutti gli elementi form */
input,
textarea,
select,
button {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  margin: 0;
  -webkit-appearance: none;
  appearance: none;
}

/* Mostra sempre un indicatore di focus visibile */
input:focus,
textarea:focus,
select:focus {
  outline: 2px solid #0EA5E9;
  outline-offset: 2px;
}

/* ❌ Non farlo mai senza un sostituto visivo */
/* input:focus { outline: none; } */

/* Layout a griglia per form a due colonne */
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.form-grid .full-width {
  grid-column: 1 / -1;
}
Non rimuovere mai l'outline di focus

Rimuovere outline: none senza sostituirlo rende il sito inaccessibile per chi usa solo la tastiera. È un requisito WCAG — sostituiscilo sempre con un indicatore visivamente chiaro.

Editor Interattivo

Un form di contatto completo con stili responsive. Prova ad aggiungere nuovi campi, cambiare i tipi di input o sperimentare con la validazione nativa.

Esercizi

✏️Metti in pratica

Esercizio A — Base

Form di Registrazione

Crea un form con:

  • First name e Last name su una riga (CSS Grid repeat(2, 1fr))
  • Email e Password (required, minlength="8")
  • Data di nascita (type="date")
  • Checkbox per i termini di servizio
  • Bottone submit stilizzato

Esercizio B — Intermedio

Sondaggio con Fieldset

Crea un sondaggio con tre sezioni <fieldset>:

  • Personal info (name, email, age)
  • Experience level (radio: Beginner / Intermediate / Advanced)
  • Interests (checkbox: HTML, CSS, JavaScript, Design)

Esercizio C — Avanzato

Form Responsive e Accessibile

Crea un form completo che:

  • Su mobile: colonna singola; su desktop: griglia a 2 colonne
  • Usa :user-valid / :user-invalid per feedback visivo
  • Focus sempre visibile (niente outline: none senza sostituto)
  • Ogni campo ha label con for/id corrispondenti