Applicare uno stile completamente personalizzato agli elementi di un form
può essere un'impresa abbastanza difficile. Alcuni elementi come i radio e i
bottoni vengono visualizzati in modo differente a seconda della combinazione
browser e sistema operativo, e questo significa avere a che fare con elementi
sempre eterogenei.
Per risolvere il problema l'ideale sarebbe poter sosituire questi elmenti
con delle immagini, analogamente a quanto si usa fare con il testo attraverso
le varie tecniche di image replacement.
Vediamo come è possibile ottenere qualcosa di simile sfruttando l'elemento
<label>
.
Struttura di un form
Il codice necessario per creare un form fa ricorso a svariati elementi: le
caselle di testo, i bottoni, le caselle a scelta multipla, i radio buttons.
Esistono però anche altri elementi che servono ad organizzarne la struttura,
come ad esempio i <fieldset>
che permettono di raggruppare
un gruppo di oggetti e le <label>
che sono delle
etichette da associare univocamente ad un altro oggetto.
Il markup standard di un semplice form potrebbe essere il seguente:
<form>
<fieldset>
<ul>
<li>
<label for="campo1">Etichetta 1</label>
<input id="campo1" />
</li>
<li>
<label for="campo2">Etichetta 2</label>
<input id="campo2" />
</li>
<li>
<label for="textarea1">Textarea 1</label>
<textarea id="textarea1" ></textarea>
</li>
<li>
<label for="submit">Be Nice</label>
<input type="submit" id="submit" value="Invia" />
</li>
</ul>
</fieldset>
</form>
Per meglio gestire il "ritmo verticale" del form, a livello di
markup si è solito organizzarlo in una lista.
Quello che ci interessa è l'elemento <label>
: esso si
associa ad un oggetto (un bottone, una casella di testo, una textarea...) del
form in modo univoco attraverso l'attributo for
. Una volta che
una label viene associata (il campo for
deve contenere
l'id
dell'oggetto interessato) essa assume, a livello di
comportamento (behavior), le stesse caratteristiche dell'oggetto
riferito: questo significa che se associamo una label ad una casella di testo
in questo modo:
<label for="input1">Etichetta 1</label>
<input id="input1" />
Ogni volta che andremo a cliccare sulla label, l'elemento associato
(input1
) prenderà il focus (cioè, nel caso della casella di
testo, apparirà la barra lampeggiante che indica che si può iniziare a
scrivere). E vale anche l'opposto, se clicchiamo direttamente sull'
<input>
anche la label risulterà attiva.
Rendiamo tutto più chiaro attraverso un esempio. Aggiungiamo questa
semplice regola CSS:
input:focus { outline: 2px solid red; }
Questa regola fa si che, se l'elemento <input>
ha il
focus, verrà evidenziato di rosso. Adesso aprite l'esempio e provate a cliccare sulla
label.
In realtà quando si dice che vale anche l'opposto, cioè cliccando
sull'input si da il focus anche alla label, non stiamo dicendo
completamente il vero. L'elemento <label>
è
considerato un elemento inline (come uno
<span>
) e non può essere bersagliato dalla pseudoclasse
:focus
perchè la caratteristica focus è propria di quegli
elementi che possono essere modificati dall'input utente (ad
esempio, come scrivere su una tastiera).
Label Replacement
Visto che la label è considerata un elemento inline risulta molto più
semplice ri-disegnarla attraverso i CSS. E visto che abbiamo anche verificato
che, una volta collegata ad un elemento di un form, essa influenzerà tutti
gli stati di quell'elemento, siamo pronti a tirare le conclusioni della
tecnica.
L'idea è questa:
- Applicare uno sfondo grafico alla label, un bottone grafico ad
esempio - Nascondere l'elemento del form cui è associata (come un
<input>
) - Utilizzare la
<label>
come se fosse l'elemento
associato.
Il primo punto è molto semplice: è solo questione di disegnare qualcosa e
applicarlo alla <label>
attraverso la proprietà
background:
label { background: url(bottone.png) no-repeat; }
Anche per quanto riguarda il secondo punto non c'è niente di complicato,
possiamo ad esempio fare così:
input { position: absolute; margin-left:-999999px; }
Una volta nascosto l'elemento, il terzo punto diventa una cosa
automatica.
Vediamo la tecnica all'opera, portando come esempio la sostituzione di un
<input type="submit">
(il bottone Invia dei
form).
Button Label Replacement
Per semplicità prendiamo come cavia un form composto solo da un etichetta
e un bottone::
<form>
<label for="invia"></label>
<input type="submit" id="invia" value="Invia" />
</form>
Disegnamo un bottone grafico da sostiuire al button vero e proprio, come
questo:
Dopodiché applichiamo come sfondo alla label:
label { background: url(send.png) 0 0 no-repeat;
display:block; width: 60px; height: 21px; }
Adesso dobbiamo preoccuparci di nascondere l' <input>
dal documento, e per farlo ci bastano un paio di regole di foglio di
stile:
input { position: absolute; left: -9999px }
Ma non fisice qui, visto che la <label>
interpreta tutti gli stati è possibile giocare con le
pseudo-classi :hover
e :active
.
Disegnamo atre due varianti dello stesso bottone, una per ogni stato:
e aggiungiamo queste due regole CSS:
label:hover { background: url(send-hover.png) 0 0
no-repeat; }
label:active { background: url(send-active.png) 0 0 no-repeat; }
Ecco il nostro bel form all'opera.
Notiamo subito una cosa che potrà far storcere il naso a chi
(giustamente) ha un occhio di riguardo verso la semantica e il
corretto utilizzo dei tag html: la label è vuota. Questo di
per sé non è un errore, anche se concettualmente è sbagliato: il motivo che
ci costringe a lasciare la label priva di contenuto è il fatto che un
eventuale testo, andrebbe a coprire il bottone grafico utilizzato come
sfondo.
In realtà per salvare "capra e cavoli" si potrebbe
tranquillamente inserire ugualmente il testo e sostituirlo con il bottone
grafico attraverso una tecnica di image replacement.
Ad esempio, scegliendo di utilizzare come tecnica la CoverUp
Span, possiamo riscrivere la label in questo modo:
<label
for="invia"><span></span>Etichetta</label>
e ri-definire le regole del CSS in questa maniera:
label { position: relative; display:block; width: 60px;
height: 21px; overflow: hidden; }
label span { position: absolute; background: url(send.png)
0 0 no-repeat; display:block; width: 100%; height: 100%; }
label:hover span { background: url(send-hover.png) 0 0
no-repeat; }
label:active span { background: url(send-active.png) 0 0
no-repeat; }
Ecco il nostro bottone grafico in funzione,
semanticamente corretto.
Come visto, la tecnica non è per niente complicata e può essere
tranquillamente applicata a qualsiasi altro elemento di un form: ad esempio,
potreste provare con i radio button.
Conclusioni
Per quanto riguarda la questionecompatibilità, la label
replacement funziona con tutte le ultime versioni dei maggiori browser
(Firefox, Opera, Internet Explorer, Safari e Google Chrome).
Non è però compatibile completamente con Internet Explorer (la versione 6)
per quanto riguarda il cambio di sfondo a seconda dello stato del bottone:
questo perchè IE non supporta l'utilizzo delle pseudo-classi
:hover
e :active
all'infuori che per gli elementi
link.
Per approfondimenti sulle label si rimanda al manuale del
w3, e sul loro uso corretto (forma implicita contro forma
esplicita) c'è un interessante paragrafo
in HTML Techniques for WCAG 2.0.
Gli esempi visti sono disponibili per il download. Alla prossima.