Dopo aver visto come Elementi essenziali e supplementari nella costruzione dei form in questo articolo vedremo come sia possibile personalizzare e impaginare i form attraversoesempi concreti che coinvolgono html e fogli di stile.
Form(a) e funzione
Un principio noto del design è che la forma segue la funzione. È un concetto molto semplice: si sostiene che la forma di un oggetto è conseguenza del suo scopo. Provate per esempio a immaginare un paio di forbici con una forma diversa... sarebbe possibile? Potreste usarle? E soprattutto.. riconoscereste subito che sono forbici? Tale principio si può applicare anche al webdesign, modificandolo in la presentazione segue la funzione.
Il modo in cui vengono presentati di default gli elementi dei form dipende molto dal sistema operativo e dal browser in uso. Ad essi si possono applicare molte proprietà CSS, come mostrato nell'articolo Moduli con stile: usare i CSS con i form, ma ci sono alcuni punti fermi che andrebbero tenuti in considerazione. Vediamo un paio di esempi da non seguire che ho "catturato" sul web:
Come si può notare i due campi di input e il bottone di submit hanno la stessa presentazione. A prima vista si fatica a riconoscere il bottone di submit... Il prossimo esempio è un caso in cui si è voluto imitare l'apparenza di un modulo cartaceo:
&46;&46;&46;a tal punto che potrebbe venire in mente all' utente di stampare la pagina
e compilare il modulo con carta e penna.
Il punto essenziale è che l'utente dovrebbe poter riconoscere un modulo on-line e le sue parti, e i CSS per presentare elementi di form andrebbero usati con moderazione. Campi di input dovrebbero avere sfondo bianco o molto chiaro e bordi ben visibili, il bottone di submit dovrebbe avere un colore che spicca e preferibilmente bordi differenti da quelli degli altri elementi dei form.
Vedremo alcuni possibili modi di personalizzazione dei singoli elementi dei form negli esempi dell'articolo. Prima di procedere con il layout dei form, un paio di premesse.
Non ereditarietà delle proprietà CSS per gli elementi dei form
Una cosa da considerare lavorando con i form è che i loro elementi (in particolare input, select e textarea) non ereditano nessuna proprietà CSS dai loro antenati. Per esempio, se nel codice HTML un form è contenuto in un div con sfondo blu e carattere serif, i campi di input non ne risentiranno minimamente, così come non influisce se la pagina ha testo con dimensionamento relativo o fisso: il testo degli input resterà comunque della stessa dimensione (almeno con Internet Explorer). L'unico modo per personalizzare elementi di form è quindi intervenire direttamente sugli stessi.
Il visual formatting model degli elementi dei form
Prima di iniziare il nostro viaggio attraverso il layout dei form, è importante capire come vengono trattati gli elementi dei form all'interno di una pagina. Gli elementi dei form, come input (e anche elementi quali img e object) sono elementi replaced (rimpiazzati). Gli elementi replaced sono elementi molto particolari:
- Vengono resi all'interno di una pagina HTML dal browser e dal sistema operativo;
- hanno dimensione intrinseca non nulla;
- vengono resi di default come elementi inline ma...
- si può attribuir loro una dimensione esplicita attraverso i CSS.
Form e struttura
I form sono molto particolari, dal momento che gli elementi che li compongono, come abbiamo visto, sono replaced e soprattutto inline. Un form, a differenza del layout di un sito che si può prestare a molteplici disposizioni delle parti, ha bisogno di un minimo di struttura nel codice, e la presentazione dei form dovrà seguirne la codifica HTML.
È vero che si possono realizzare form, anche ben presentati, con markup minimale (ossia usando solo fieldset, label e input e attribuendo ad essi classi e id) ma prima di procedere ad "impaginare" un form solo attraverso i fogli di stile bisognerebbe dare uno sguardo a come rende solo grazie al codice HTML. In maniera molto simile verrà visualizzato su un browser testuale come Lynx. Per questi motivi, a parer mio, un minimo di struttura nel markup dei form è necessaria, soprattutto in form corposi. Può essere realizzata in diversi modi, vediamo come.
Layout dei form: la soluzione con le tabelle
Come abbiamo detto la struttura dei form è quasi inseparabile dal suo contenuto. Gli appassionati dei fogli di stile sanno bene che le tabelle dovrebbero essere usate solo per dati tabellari, ma personalmente non ci vedo niente di male a impaginare form con le tabelle. Queste ricalcano la schematicità tipica dei form, sono robuste, hanno compatibilità con tutti i browsers e sono facili da realizzare (ancora di più con un editor visuale). Non vedremo esempi con le tabelle, ma alcuni piccoli accorgimenti da tenere in conto:
- Se possibile, non usare tabelle annidate;
- usare fieldset per raggruppare elementi logicamente correlati;
- l'ordine di codice di label e campi di imput relativi dovrebbe essere il più naturale possibile, ossia etichetta e campo di input dovrebbero stare nella stessa cella o al limite in celle adiacenti sulla stessa riga;
- se si eliminassero virtualmente le righe e le celle di una tabella, l'ordine degli elementi del form dovrebbe seguire l'ordine di immissione dei dati da parte dell' utente.
Seguire questi suggerimenti vi sarà utile per realizzare form basati su tabelle un po' più accessibili. Le alternative per impaginare form sono comunque diverse. Risulteranno più leggere a livello di codice HTML, ma richiederanno un maggior lavoro dal versante CSS. E in tal caso è importantissimo testare il lavoro sul maggior numero di browsers. Vediamo subito una prima soluzione.
Layout dei form con i <br>
Come abbiamo detto, gli elementi di input dei form sono inline, e quindi si susseguono orizzontalmente proprio come parole all'interno di un paragrafo. Allo stesso modo con cui si forza l'andata a capo del testo, si può procedere quindi con i campi dei form, ossia usando i br. Il primo esempio è un semplice modulo di contatto. Vediamo il codice HTML, in cui sono evidenziati in grassetto gli elementi aggiuntivi al semplice codice minimale:
<form method="post" action="">
<fieldset>
<legend>Modulo di contatto</legend>
<p>Per contattarci, compila il modulo sottostante,
avendo cura di fornire un indirizzo e-mail valido
al quale ti risponderemo al più presto.</p>
<label for="nome">nome: </label>
<input type="text" id="nome" name="nome"><br>
<label for="cognome">cognome: </label>
<input type="text" id="cognome" name="cognome"><br>
<label for="email">email: </label>
<input type="text" id="email" name="email"><br>
<label for="message">messaggio: </label>
<textarea id="message" name="message" rows=8 cols=20></textarea><br>
<input type="submit" id="go" value="spedisci">
</fieldset>
</form>
In sostanza si sono aggiunti dei br dopo ciascun campo di input e dopo la select. Trattandosi di un form con un unico fieldset è stato infatti possibile racchiudere il bottone di input al suo interno, cosa che andrebbe evitata se si fosse trattato di un form con diversi fieldset.
Prima di procedere con i CSS, diamo uno sguardo alla pagina senza foglio di stile. Certo bisogna lavorarci un po' su, ma quattro semplici br ci forniscono già un discreto punto di partenza. Per prima cosa attribuiamo colore di sfondo, larghezza e bordi del form. Dato che il fieldset è unico, si può usare la legenda proprio come se fosse il titolo del form, eliminando i tipici bordi dal fieldset. È il massimo che possiamo fare per personalizzare la legend, che ha comportamenti molto differenti sui diversi browser. Aggiungiamo un po' di margini al paragrafo informativo. Ecco le regole:
form{width: 350px;border: 5px solid #7EA4D8;
padding-bottom: 10px;background-color: #BBD8FF}
fieldset{border: 0px solid #000}
legend{font: bold 140%/1.6 Arial,sans-serif;color: #27518A}
form p{margin: 10px 10px 20px}
Se si vuole ottenere una perfetta consistenza cross-browser andrà usato il
Capire il box model
per il form, dato che IE 5.x considera i bordi parte dei 350 pixel
del form. A questo punto arriviamo alla parte centrale. Le label
verranno rese float, così da poter attribuire loro una dimensione
e un'altezza all'incirca pari a quella dei campi di input attraverso la proprietà
line-height, che ci consente inoltre di allineare centralmente il
testo con il relativo input. Il testo delle label verrà allineato a destra per
dare una maggiore vicinanza ai campi di input. Ecco il codice:
fieldset label{float:left;width:100px;
line-height: 23px;margin-right: 5px;text-align: right}
A questo punto andiamo a definire le regole per input e textarea, personalizzando i bordi
e aggiungendo un po' di margini:
fieldset input,textarea{ margin-bottom:5px;border-style: solid;
border-color: #778AA2 #7EA4D8 #7EA4D8 #778AA2;
border-width: 2px 1px 1px 2px}
Infine diamo al br il clear e posizioniamo il tasto di submit, aggiungendogli anche sfondo
e bordi:
br{clear:left}
input#go{margin: 10px 0 0 108px;border-style: solid;
border-color: #FFF #333 #333 #FFF;
border-width: 1px 2px 2px 1px;
background: #69c url(sfondobottone2.jpg) repeat-x}
Da notare che la personalizzazione dei bordi sul bottone di submit prevale su quella più generica sui campi di input, in quanto gli abbiamo attribuito un selettore di id che ci consente una regola più specifica. Il form è così completo e risulta ben organizzato visivamente: rivediamolo. Se avessimo voluto impaginarlo attraverso una tabella, probabilmente sarebbe stata di cinque righe e due colonne, per un totale di dieci celle.
Dopo aver visto il modo per impaginare i form usando i br, vedremo qui diversi metodi alternativi. L' impaginazione dei form senza l'uso di tabelle può risultare un processo complesso, e uno stesso risultato visivo può essere realizzato in diversi modi. Le possibili soluzioni saranno adottate in base a fattori quali la complessità del form e il risultato che si vuole ottenere.
Layout di form con i div
Potrà sembrare strano, ma personalizzare un form con meno campi di quello della
prima parte dell'articolo può risultare più difficile se i campi non sono tutti
omogenei. Un semplice checkbox e la relativa label possono infatti complicarci
le cose. Il prossimo esempio è un modulo
di login per la posta. In casi simili può risultare utile racchiudere campi
dello stesso tipo in div con adeguata classe. Vediamo il codice HTML,
in cui ho evidenziato i div aggiuntivi:
<form method="post" action="">
<fieldset>
<legend>Leggi la tua posta</legend>
<div class="in">
<label for="user">nome utente: </label>
<input id="user" name="user">
</div>
<div class="in">
<label for="pass">password: </label>
<input type="password" id="pass" name="pass">
</div>
<div class="cb">
<input type="checkbox" id="remember" name="remember">
<label for="remember">ricordami il nome utente su questo computer</label>
</div>
</fieldset>
<div>
<input type="submit" id="go" value="entra">
</div>
</form>
Vediamo come rende
la versione senza stile: la marcatura aggiuntiva è senza dubbio di aiuto. Ora
procediamo con il CSS. Per prima cosa definiamo gli stili sul form, sul fieldset
e sulla legend. Anche in questo caso, trattandosi di un form con un unico campo
di testo, la legend farà da titolo al form stesso. Al form è stata aggiunta una
semplice immagine di sfondo per renderlo più accativante e soprattutto per aiutare
l'utente a riconoscere subito la funzione del form:
form{width:250px;padding:5px 0;border: 2px solid #ccc;
background: #DDE4FF url(mail.jpg) no-repeat top right}
fieldset{border: 0px solid #000}
legend{font: bold 140% Arial,sans-serif;color: #27518A}
Ora aggiungiamo i margini dei div contenenti i campi di input:
div.in, div.cb{margin: 10px 0 10px 10px}
A questo punto sistemiamo le label e i relativi campi di testo. È in
questo caso che ci viene utilissimo aver definito una classe in per
i div contenenti campi di input testuali. Attraverso il selettore discendente
sarà infatti possibile definire regole specifica solo per le label e gli input
contenuti nel loro interno:
div.in label{float:left;width:90px;line-height:23px}
div.in input{width:120px}
La due regole sopra infatti non avranno effetto sul div con classe cb,
la cui label e il relativo checkbox non necessitano di regole aggiuntive. Ora
ci resta solo il bottone di submit:
input#go{margin-left: 100px;border: 2px solid #27518A;
background: #ccc url(sfondobottone.jpg) repeat-x}
Il nostro form è così ultimato:
con qualche regola CSS lo abbiamo reso molto più gradevole e organizzato rispetto
alla versione senza stile.
Un'alternativa grazie ai CSS
Form ben strutturati a livello di codice HTML consentono una discreta personalizzazione
con i fogli di stile. Senza modificare il codice del modulo appena visto ma agendo
solo sul CSS si può ottenere, ad esempio, questo
risultato, in cui le label sono state rese block-level e il checbox nascosto.
Ecco il CSS per intero:
form{width: 120px;border: 2px solid #6D8CC6;
background-color: #D2E3F3;
color: #000;text-align: center}
fieldset{border: 0px solid #000}
legend{color: #304A78;font-weight:bold}
div.in{margin:5px 0}
div.in label{display:block}
div.in input{width:100px}
div.cb{display:none}
input#go{margin:5px 0;border: 1px solid #425578;
background: #99F url(sfondobottone3.jpg) repeat-x}
Seppure si siano aggiunti dei div al codice HTML minimale, è possibile comunque personalizzare attraverso i CSS il nostro form in diversi modi. Per il lettore realizzare ancora un'altra versione solo intervenendo sul CSS, oppure realizzare uno dei due esempi appena visti usando esclusivamente br e classi su label e input potrebbero costituire un buon esercizio. Nella terza e ultima parte affronteremo la realizzazione di layout di form avanzati, sempre contando sulla potenza dei fogli di stile.
Codice ed esempi nel file zip allegato.
Finora abbiamo trattato form piuttosto semplici, costiuiti da pochi campi di input e un solo fieldset. Sarà già chiaro al lettore che non c'è un unico modo di procedere nella costruzione di form senza l'ausilio di tabelle. Una possibile strategia generale è la seguente:
- Decidere i gruppi di dati che l'utente dovrà immettere
- Per ciascuno di essi, quali e che tipo di campi di input
- A questo punto si potrà codificare il form in maniera minimale, ossia usando solo fieldset, label e campi di input
- Il codice HTML così risultante andrà visualizzato senza l'aggiunta di fogli di stile
- Si dovrà procedere aggiungendo div o br per dare un minimo di struttura al form, finché visualizzando la pagina non si abbia una disposizione pratica da affinare solo attraverso i fogli di stile
- Una volta indivuduate le caratteristiche dei campi di input si procederà attribuendo classi e id dove necessario a fieldset, label e input e ad eventuali div aggiuntivi per consentire di realizzare regole specifiche attraverso i fogli di stile
- A questo punto la parte HTML dovrebbe essere conclusa. Si potrà allora procedere
con il foglio di stile, usando in particolare selettori di tipo, di id, di classe
e discendente. Nel caso fosse necessario, si dovrà tornare al punto precedente.
Durante le codifica del foglio di stile, è bene testare sul maggior numero di
browser e non solo su quello predefinito.
Prima di procedere con il nostro ultimo esempio, vediamo tre tecniche che potranno
risultare utili in alcuni casi.
Label come contenitori
Sembrerà banale.. ma lo spazio orizzontale disponibile in una pagina è limitato,
al contrario di quello verticale. Per form con molti campi, in cui si voglia rendere
l'etichetta sopra il campo di input, può venire utilissimo usare la label come
contenitore. Vediamo come fare con HTML e CSS. Ecco l'HTML:
<label for="nome">nome: <input id="nome" name="nome"></label>
E il CSS:
label{float:left;text-align:center}
label input{display:block;width:150px}
Rendendo il campo di input block-level, il testo dell'etichetta viene reso
in un contenitore anonimo block-level, come spiegato nell'Il box model. In questo modo potremo affiancare due o più label con relativo
campo di input e ci sarà possibile andare a capo usando dei br con
clear:left impostato. Inoltre, ci potremo risparmiare molti contenitori
aggiuntivi, mantenendo il codice leggero e il form ben strutturato. Ecco un'immagine
che rappresenta un fieldset dell'ultimo esempio che vedremo:
Checkbox schematici
Label come contenitori si possono utilizzare anche per i checkbox, ottenendo
grazie ai CSS una buona disposizione. Vediamo il codice HTML:
<label for="musica1">
<input id="musica" type="checkbox">
musica pop
</label>
Supponendo di racchiudere i checkbox in un fieldset con id="check"
ci basta un unica regola CSS che sfrutta il selettore discendente:
fieldset#check label{float:left;width:120px}
Anche in tal caso è possibile usare dei br per andare a capo,
oppure se il nostro form ha una larghezza fissa, i checkbox si disporranno secondo
il numero massimo possibile per riga, per poi continuare nella riga successiva.
Ecco una schermata dell'esempio che stiamo per vedere e che sfrutta questa tecnica
senza neanche i br dato che il form è costretto in larghezza:
Si pensi che lo stesso effetto con le tabelle avrebbe richiesto ben dodici celle, appesantendo di molto la pagina.
Contenere i float
Può capitare che lavorando con la proprietà float ci si trovi in situazioni simili:
Lo strano fenomeno è dovuto al fatto che il float
va contenuto. Per consentire al fieldset di includere completamente i suoi
campi di input, basterà prima di chiuderlo (ossia dopo il suo ultimo campo di
input) aggiungere un semplice br con clear:left impostato
via CSS.
Esempio completo: un modulo di registrazione
Arriviamo all'esempio conclusivo
sul layout dei form. Si tratta di un form di medie dimensioni per la registrazione
utenti. Il codice HTML è piuttosto corposo, ma comunque quasi minimale. Si sono
solo attribuite classi e id ai fieldset, ed usati estensivamente i br
per dare un minimo di struttura alla pagina anche nella versione
senza stile. Tutte le label contengono il relativo campo di input. Per brevità
riporto una versione accorciate del codice HTML, che comunque potrete visualizzare
per intero dalla pagina ed è anche a disposizione per il download:
<fieldset class="in">
<legend>dati generali</legend>
<label for="nome" class="req"><strong>* </strong>nome: <input id="nome" name="nome"></label>
<label for="cognome" class="req"><strong>* </strong>cognome: <input id="cognome" name="cognome"></label><br>
<!--ecc --><br>
</fieldset>
<fieldset class="in">
<legend>contatti</legend>
<label for="tel">telefono: <input id="tel" name="tel"></label>
<label for="fax">cellulare: <input id="fax" name="fax"></label><br>
<label for="email" class="req"><strong>* </strong>email: <input id="email" name="email" size=42 class="large"></label><br>
</fieldset>
<fieldset id="check">
<legend>interessi personali</legend>
<label for="musica1"><input id="musica1" name="pers" type="checkbox">musica pop</label>
<label for="musica2"><input id="musica2" name="pers" type="checkbox">musica classica</label>
<!--ecc.. --><br>
</fieldset>
<fieldset id="account" class="in">
<legend>il tuo nuovo account</legend>
<p>il <strong>nome utente</strong> ecc...</p>
<label for="user" class="req"><strong>* </strong>nome utente:<input id="user" name="user"></label><br>
<label for="pass" class="req"><strong>* </strong>password:<input id="pass" name="pass"></label><br>
<!--ecc --><br>
</fieldset>
<fieldset id="agree">
<legend>condizioni di utilizzo</legend>
<div id="cond">
<p>Qui le condizioni di utilizzo..</p>
<div>
<label for="accetto"><input id="accetto" name="accetto" type="checkbox">ho letto e accetto le condizioni di utilizzo</label><br>
</fieldset>
Come si può notare, il form è costituito da quattro fieldset. A quelli contenenti
campi di input testuale è stato attribuita una class="in", mentre
a quello contenente il checkbox una class="check". Ai campi di input
lunghi è stata attribuita una class="large". E poi si sono usati
i br sia per mandare a capo che per contenere il float.
Il css non risulta particolarmente complicato o pesante, e fa un uso abbondante
del selettore discendente. Vediamolo per intero:
fieldset{padding: 8px;border: 1px solid #B02F2F;margin-bottom: 20px}
legend{padding: 0 5px;text-transform: uppercase;color: #B02F2F}
label.req strong, strong.asterisco{font-weight: bold;
font-family: verdana,sans-serif;color: red}
input:focus{background-color: #ffc}
br{clear:left}
fieldset.in label{float: left;text-align: center;margin: 0px 10px 5px 0}
fieldset.in input,select{display: block;width: 170px}
fieldset.in input.large{width: 355px}
input#cap,input#provincia{width: auto}
fieldset#check label{float: left;width: 120px}
fieldset#account p{float: right;width: 190px;color: #185DA1;margin-top: 10px}
fieldset#agree div#cond{width: 355px;height: 150px;overflow: auto;
border:1px solid #666;margin: 10px 0;background-color: #f7f7f7}
fieldset#agree div#cond p{margin:0 5px 6px}
div#bottone{text-align:center}
input#go{border: 1px solid #666;
background: #ACCDF6 url(sfondobottone.jpg) repeat-x}
Il risultato è ben presentato
e ha un markup quasi minimale, a parte i br.
Nello zip allegato codice ed esempi.