I form sono senza dubbio uno strumento fondamentale per qualsiasi sito web. Ci offrono la possibilità di ricevere comunicazioni di ogni tipo e rappresentano, quindi, un canale aperto di comunicazione con i nostri visitatori.
Indipendentemente dal linguaggio utilizzato (lato server come ASP, PHP o PERL oppure lato client come HTML) tutti i moduli hanno in comune una struttura visibile al navigatore, scritta in html semplice. Ecco un banalissimo esempio:
<form name="saibal" action="....." method="post">
<input name="prova" type="text" size="25">
<input type="submit" name="submit" value="Invia">
</form>
Per determinare la tecnologia utilizzata basterà "leggere" l'action del form e vedere a che tipo di pagina punta (mi riferisco al tipo di estensione presente).
In questo articolo, con l'ausilio di javascript e fogli di stile, tenterò di spiegare qualche suggerimento che può essere utile nella realizzazione "strutturale" di un qualsiasi modulo. Per chi volesse avere una panoramica generica sulla scrittura di form può leggere l'Introduzione ai FORM della guida HTML.
Chiunque abbia avuto a che fare con la costruzione di un form si sarà certamente accorto della differenza che può esserci, in alcuni casi, nella visualizzazione a video tra Explorer e Netscape (in particolare la versione 4.x; per fortuna l'uscita di Netscape 6.x ha decisamente ridotto il divario).
In pratica (mi rivolgo a chi non abbia mai avuto modo di verificarlo) i singoli elementi del form vengono rappresentati con dimensioni diverse a seconda del browser utilizzato; ciò dipende, principalmente, dalla natura stessa dei navigatori che, tra le particolarità che caratterizzano il loro DOM, hanno anche una differente interpretazione dei campi.
Penso sia capitato a molti di realizzare un bel modulo (perfettamente integrato con il resto del sito se visto con Explorer) e di scoprire, invece, che con Netscape la grafica veniva "stravolta" da qualche textarea apparentemente troppo lunga.
Uno degli obiettivi del tutorial sarà proprio quello di cercare di ovviare a questo problema. Personalmente conosco due ottime soluzioni per riuscire ad ottenere moduli di dimensioni a video praticamente identiche, sia con IE che con NN: un metodo utilizza esclusivamente javascript mentre l'altro si avvale dei css.
Prima di continuare, però, vorrei dare risposta ad una domanda che sembra essere molto diffusa (almeno tra chi è alle prime armi): come eliminare lo spazio lasciato da un form quando inserito in una tabella? (problema che peraltro non si presenta con Netscape 6.x).
Per capire a cosa mi riferisco guardate questo esempio con Explorer o Netscape 4.x:
Ho impostato appositamente il bordo della tabella ad "1" per far notare che tra il bottone di submit e la fine della tabella stessa c'è uno spazio ben visibile anche se, nel codice, non abbiamo inserito nessun <br> dopo la chiusura del tag </form>.
Ebbene, probabilmente i puristi dell'html storceranno il naso nel leggere quanto sto per scrivere ma, come spesso accade, il fine giustifica i mezzi; provate a riscrivere la stessa pagina spostando i tag di apertura e di chiusura del form tra i tag <tr> della tabella, in questo modo:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Spazio form</title>
</head>
<body>
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<form name="saibal" action="....." method="post">
<td>
<input name="prova" type="text" size="25">
<input type="submit" name="submit" value="Clicca & Godi">
</td>
</form>
</tr>
</table>
</body>
</html>
Qui si trova l'esempio pratico: Esempio numero 2
Vi sarete accorti che è scomparso l'antiestetico spazio che poteva rovinarci il layout del sito. Se, per scrivere questo codice, utilizzate programmi come Homesite o Dreamweaver, è probabile che vi venga segnalato un errore... ma personalmente non mi preoccuperei più di tanto; è vero che, come già detto, il metodo utilizzato non è del tutto ortodosso per le specifiche del W3C ma, aggiungerei anche, che i broswer attualmente in circolazione (compreso l'odiato/amato Netscape 4.x) non hanno mai dato problemi di visualizzazione.
Se invece non ne volete proprio sapere di andare contro le specifiche ufficiali utilizzate questo semplice foglio di stile (da inserire tra i tag <head> della pagina):
<style type="text/css">
form {margin-bottom : 0; }
</style>
Inutile aggiungere che il css non funzionerà con Netscape 4.x .
Torniamo adesso al problema di come creare moduli "universalmente" uguali, indipendentemente dal browser utilizzato.
La prima soluzione utilizzerà solamente javascript; personalmente non è il metodo che preferisco (vi accorgerete in seguito della comodità dei css) ma potrebbe essere utile a chi non ha molta dimestichezza con i fogli di stile.
Supponiamo di dover inserire un form in una pagina qualsiasi. Solitamente viene utilizzato il browser predefinito per testare la pagina e, successivamente, si passa alla visualizzazione con un altro navigatore per le "rifiniture" generali.
Se utilizzate principalmente Netscape non dovrete cambiare metodo di lavoro mentre, se siete affezionati di casa Microsoft, per questa volta vi chiedo di costruire il modulo utilizzando come riferimento Netscape.
È molto importante che utilizziate il parametro size="valore" all'interno di ogni input, ad esempio:
<input name="prova" type="text" value="" size="15">
Una volta ottenuto un buon risultato grafico con NN, possiamo passare all'introduzione del javascript che farà il resto del lavoro.
Il codice che sto per scrivere ha effetto solo su Explorer e ridimensiona automaticamente, in base ad una percentuale scelta da noi, tutti gli elementi di un modulo.
Tra i tag <head> della pagina che contiene il form inseriamo quanto segue:
<SCRIPT type="text/javascript">
function ridimensiona(decNum){
if(navigator.appName != 'NetscapÈ){
var incrVal="."+decNum;
for(i=0;i<document.forms.length;i++){
for(j=0;j<document.forms[i].elements.length;j++){
var formObj=document.forms[i].elements[j];
if(formObj.type.toLowerCase() == "text" || formObj.type.toLowerCase() == "password" || formObj.type.toLowerCase() == "file"){
formincr=formObj.size*eval(incrVal);
formObj.size=formObj.size+formincr;
}else if(document.forms[i].elements[j].type.toLowerCase() == "textarea"){
formincr=formObj.cols*eval(incrVal/2);
formObj.cols=formObj.cols+formincr;
}
}
}
}
}
</script>
Successivamente, nel <body>, inseriamo il nostro modulo:
<form name="saibal" action="....." method="post">
<input name="prova" type="text" size="25">
<input type="submit" name="submit" value="Invia">
</form>
Infine, immediatamente dopo il tag di chiusura </form>, scriviamo questa stringa che ha la funzione di richiamare la funzione "ridimensiona" del javascript:
<SCRIPT type="text/javascript">
ridimensiona('15');
</script>
Il numero "15" è la percentuale di ridimensionamento che può essere cambiata in base alle esigenze (solitamente un valore compreso tra 15 e 25 va più che bene). Supponiamo anche di avere più di un form nella stessa pagina e di volerli ridimensionare tutti.
Le strade che possiamo seguire sono principalmente due:
- Incollare una sola volta questo codice a fine pagina:
<SCRIPT type="text/javascript">
ridimensiona('15');
</script> - Mettere lo stesso codice dopo ogni form
Per vedere le modifiche apportate dallo script possiamo visualizzare i primi due esempi:
- Esempio numero 3 (senza utilizzo del javascript)
- Esempio numero 4 (con utilizzo del javascript)
Il primo documento (da visualizzare con i vari browser) è stato ottimizzato per Netscape e non è stato inserito il codice Javascript.
Visualizzando la stessa pagina con IE noteremo che i campi del form sono più corti rispetto a quelli visti precedentemente con NN.
Utilizzando il codice, nell'esempio numero 4, possiamo notare come i campi siamo molto simili in lunghezza. È stata usata una percentuale del 15% ma è possibile impostare un valore diverso. Così facendo il risultato ottenuto nella visualizzazione "a video" è quasi identico.
Lo script, in particolare, "agisce" su determinati elementi:
- Campi Text
- Campi Password
- Campi File
- Textarea
Se da una parte questo javascript ci aiuta a migliorare l'aspetto dei moduli, dall'altra dobbiamo rilevare alcune controindicazioni derivanti dal suo utilizzo.
Prima di tutto siamo costretti ad inserire diverse righe di codice in tutte le pagine contenenti i form; inoltre potremmo avere ancora delle differenze estetiche visto che il javascript viene totalmente ignorato da Netscape 6.x.
Possiamo dire che questa, forse, è la migliore soluzione per chi abbia ancora bisogno di una perfetta compatibilità con l'ormai obsoleto Netscape 4.x.
Se invece Netscape 4.x non è tra i nostri browser prioritari, possiamo utilizzare il secondo metodo che fa uso dei fogli di stile.
Personalmente è la soluzione che preferisco per vari motivi (motivi che restano comunque soggettivi e non assoluti).
Con i CSS possiamo avere un controllo totale sull'aspetto dei campi; il codice della pagina è decisamente pulito; possiamo aggiungere un tocco di originalità al nostro lavoro (vedremo poi come); tutte le eventuali modifiche sono veloci e non richiedono molto tempo.
Anche se alcuni attributi (come width per esempio) non vengono interpretati da Netscape 4.x, si può ovviare facilmente a questo problema con un piccolo stratagemma e, di fatto, creare dei moduli esteticamente cross-browser.
Partiamo dal precedente modulo base:
<form name="saibal" action="....." method="post">
<input name="prova" type="text" size="25">
<input type="submit" name="submit" value="Invia">
</form>
Utilizzato così com'è si ripresenterà il solito problema: il campo TEXT sarà, a video, leggermente più lungo in Netscape 4.x rispetto ad Explorer e a Netscape 6.x.
Per risolvere definitivamente questo inconveniente è giunto il momento di inserire questi CSS tra i tag <head> della pagina:
<style>
.campiform {width: 55mm;}
</style>
Non facciamo altro che impostare una classe (chiamata in questo caso "campiform") che determina, in modo univoco, la lunghezza dei campi mediante l'attributo width dei fogli di stile.
Questo CSS sarà interpretato correttamente da Explorer e NN 6.x o sup. (con i quali i campi saranno di fatto identici) mentre, apparentemente, resterà irrisolto il problema Netscape 4.x che continuerà a restituire dei campi più lunghi del normale.
Se però abbiamo già detto che l'attributo width non viene letto dall'obsoleto NN 4.x, ciò non vuol dire che non sia possibile utilizzare l'attributo size del campo; anzi: proprio l'utilizzo congiunto di questi due parametri è la chiave di volta per risolvere il problema iniziale.
I browser più avanzati prenderanno in esame solo i CSS, mentre i browser più vecchi interpreteranno solo l'attributo size. Giocando e prendendo un po' di confidenza con le misure sarà estremamente semplice ottenere dei form molto simili che non stravolgeranno il layout.
Vi presento un esempio che mi servirà per dimostrare ciò che abbiamo detto finora. Il modulo di seguito presentato è praticamente identico se visto con i tre browser finora analizzati:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Form</title>
<style>
.campiform {width: 55mm;}
</style>
</head>
<body>
<table border="1" cellpadding="0" cellspacing="0">
<tr>
<form name="saibal" action="....." method="post">
<td>
<input name="prova" type="text" size="25" class="campiform">
<input type="submit" name="submit" value="Clicca & Godi">
</td>
</form>
</tr>
</table>
</body>
</html>
Per richiamare la classe non abbiamo fatto altro che inserire class="campiform" all'interno del tag del campo interessato.
Explorer e Netscape 6.x, come già detto, prenderanno come riferimento l'attributo width dei css, mentre il "caro" e vecchio NN 4.x, non riconoscendo quel foglio di stile, farà riferimento al size presente nel codice. L'unica cosa che ci resterà da fare sarà quella di trovare il giusto rapporto tra i millimetri dei css ed il size del campo.
Dopo aver ottenuto dei form crossbrowser potremmo già essere soddisfatti dei risultati raggiunti; sono sicuro, però, che non avete voglia di fermarvi qui e siete esigenti almeno quanto me. Si potrebbe anche pensare di dare un tocco di originalità ai moduli che, diciamoci la verità, sono decisamente "anonimi" nella veste originale.
Giriamo pagina e vediamo subito qualche esempio più raffinato.
Può capitare, ad esempio, di aver costruito un gran bel sito (magari con grafica e testo particolarmente curati) e poi vedere un form che "cozza" decisamente con il resto delle pagine per questioni di estetica.
Ricorrendo sempre ai fogli di stile (vi starete accorgendo che, per un webmaster, è veramente indispensabile conoscerli bene) possiamo determinare il tipo di font, la grandezza ed il colore del testo. Prendiamo il foglio di stile utilizzato in precedenza e modifichiamo la classe "campiform" in questa maniera:
<style>
.campiform {width: 55mm; font-family: verdana, tahoma, arial; color: red; font-size: 10px; }
</style>
- Abbiamo ottenuto un campo del form che:
- utilizzerà una famiglia di font prestabilita (in questo caso Verdana, Tahoma e Arial)
- avrà il testo in colore rosso
- avrà il testo di grandezza 10px
Anche se non strettamente legato all'argomento moduli vorrei darvi un piccolo suggerimento sull'utilizzo dei css in questa circostanza... un trick come direbbero i professionisti :) (a tal proposito ringrazio Kuba, un utente del nostro forum). Nell'attributo size utilizzate sempre, come unità di misura, i px e non i pt. I punti, infatti, sono sempre relativi mentre i pixel sono una misura assoluta (e questo ci aiuta ad avere un pieno controllo sul testo).
Ma non finisce qui: i browser di casa Netscape (ed in particolare Navigator 4.x, anche se ci vuole coraggio a chiamarlo ancora browser) interpretano in modo differente le misure in pixel rispetto ad Explorer. Nel particolare, un testo di 10px sarà sempre più piccolo (di un pixel circa) se visto con NN rispetto ad IE ... come risolvere la questione?
È presto detto. Anzichè scrivere il canonico font-size: 10px; utilizzeremo font-size: 10.75px;
Il trucco sta proprio nell'usare numeri decimali separati da un punto. IE "leggerà" solo l'intero a sinistra del separatore, ignorando il resto (quindi avremo 10px); Netscape, invece, interpreterà il numero nel suo valore totale (10.75 appunto) restituendo un testo praticamente uguale a quello restituito da IE.
Se decidiamo di usare questo metodo ricordiamoci di rivedere le misure che avevamo dato all'attributo size per Netscape 4.x.
Ok... ora che siamo diventati abili anche nel gestire il testo nei moduli possiamo passare a qualcosa di puramente estetico. Uno dei problemi principali dei campi dei form è il fatto che poco si integrano con le pagine. C'è un modo molto semplice per tentare di rendere i campi più gradevoli e farli "fondere" con il resto del sito... e questo risultato è ottenuto sempre grazie ai fogli di stile.
Ancora una volta riprendiamo la classe "campiform" e aggiungiamo quanto segue:
border-style: solid; border-color: #006699; border-width: 1; background: #f0f0f0;
quindi otterremo:
<style>
.campiform {
width: 55mm;
font-family: verdana, tahoma, arial;
color: red;
font-size: 10.75px;
border-style: solid;
border-color: #006699;
border-width: 1;
background: #f0f0f0;
}
</style>
Provate e visualizzare l'esempio numero 7... carino eh?
In questo modo diamo sicuramente un tocco di originalità ai nostri barbosi moduli e questi fogli di stile vi permetteranno di integrare perfettamente i campi con il bel layout che avete costruito per il vostro sito.
Passiamo alle spiegazioni "tecniche": per dare l'aspetto "piatto" ai campi abbiamo utilizzato queste quattro voci:
- border-style: solid; il tipo di bordo; se avete IE 5.5 o sup. provate anche dashed al posto di solid
- border-color: #006699; il colore del bordo
- border-width: 1; lo spessore del bordo; dire che 1 va più che bene
- background: #f0f0f0; il colore di sfondo del campo
Prima di andare avanti, però, soffermiamoci sulla compatibilità di questo css. Non si riscontrano problemi con Explorer a partire dalla versione 5.x; Opera (nelle versioni più recenti) non ha dato particolari problemi; Netscape 6.x e sup. interpreta lo stile in modo adeguato ma potrebbe lasciare una sorta di piccolo "alone" intorno al campo (se avete ancora la versione 6.x, non la 7 che io giudico ottima). Se così fosse levate, dal campo input, l'attributo type="text" e tutto diventerà uguale ad Explorer.
Bene, chi manca all'appello? Credo che ormai la disperazione abbia lasciato spazio alla rassegnazione: il "caro" Netscape 4.x non riconosce quel tipo di stili. Probabilmente non ve ne importerà nulla ma questa volta c'è un ulteriore problema.
Provate a visualizzare l'esempio precedente con Navigator: non solo non interpreta lo stile in modo appropriato, ma crea anche dei problemi a livello grafico. Questa volta abbiamo un vero e proprio problema di incompatibilità che va risolto.
Non sono di certo il mago Silvan visto che non ho inventato nulla, ma dal mio piccolo cilindo magico posso tirare fuori due semplici soluzioni.
La prima vi rimanda all'articolo Riconosciamo i browser con Javascript che ho scritto qualche tempo fa. In pratica si tratta di creare due tipi diversi di css esterni ed usarli dopo aver riconosciuto il tipo di browser attraverso l'aiuto di javascript. Potremo, quindi, scrivere dei CSS ad hoc che vadano bene per Netscape, ed altri che vadano bene per tutti gli altri.
La seconda soluzione, invece, è più veloce e forse anche più raffinata. Il W3C, a partire da CSS1, ha introdotto un piccolo attributo chiamato
@import url();
Molto brevemente spiego il suo funzionamento: "@import url();" serve ad importare, nella pagina, css esterni... ha la stessa funzione del tag
<link rel="stylesheet" type="text/css" href="xxx.css">
ma con una variante: è possibile importare dei css esterni da un altro css esterno; ed è proprio questa caratteristica che noi sfrutteremo.
Forse questa è l'unica volta in cui saremo grati del fatto che NN4.x non interpreta correttamente un determinato attributo dei css.
Supponiamo di avere questa pagina:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Prova import</title>
<style>
.campiform {
width: 55mm;
font-family: verdana, tahoma, arial;
color: red;
font-size: 10px;
border-style: solid;
border-color: #006699;
border-width: 1;
background: #f0f0f0;
}
</style>
</head>
<body>
<form name="saibal" action="....." metod="post">
<input name="prova" type="text" size="25" class="campiform">
<input type="submit" name="submit" value="Clicca & Godi">
</form>
</body>
</html>
Abbiamo appena detto che una pagina di questo tipo non sarebbe compatibile con Netscape 4.x perchè alcuni attributi della classe "campiform" darebbero problemi.
A questo punto eliminiamo le righe incriminate e mettiamole in un file .css esterno, avendo cura di lasciare invariato il nome della classe (in questo caso "campiform"). In pratica apriamo il blocco note, incolliamo quanto segue (senza altre aggiunte) e salviamo con il nome di "stile.css":
.campiform {
border-style: solid;
border-color: #006699;
border-width: 1;
background: #f0f0f0;
}
Adesso riprendiamo la pagina precedente e modifichiamola in questa maniera:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Prova import</title>
<style>
/* usiamo @import prima di ogni altra classe */
@import url('stile.css');
/*impostiamo la classe */
.campiform {
width: 55mm;
font-family: verdana, tahoma, arial;
color: red;
font-size: 10px;
}
</style>
</head>
<body>
<form name="saibal" action="....." method="post">
<input name="prova" type="text" size="25" class="campiform">
<input type="submit" name="submit" value="Clicca & Godi">
</form>
</body>
</html>
Cosa abbiamo fatto? Semplice! Abbiamo impostato una classe "campiform" scegliendo il tipo di font, il colore e la grandezza del testo. Questa classe può essere definita "globale" visto che sarà interpretata correttamente da tutti i browser.
Prima della classe, però, abbiamo usato @import url(); per assegnare altri attributi alla classe "campiform".
Netscape 4.x ignorerà completamente il css esterno, mentre i browser più evoluti importeranno correttamente il foglio di stile esterno e, in pratica, "fonderanno" insieme le due classi con lo stesso nome come se fosse una unica.
L'unico accorgimento da tenere bene a mente è che @import url(); deve essere messo prima di ogni altra classe. In verità non darebbe problemi con IE neanche se fosse messo alla fine ma Netscape 6.x e sup. non fonderebbe le due classi... quindi, per non avere problemi, mettiamolo all'inizio.
Se invece avete già un foglio di stile esterno il procedimento è molto simile. Nel primo css, che importate con un classico <link rel="stylesheet" type="text/css" href="xxx.css">, create la classe "campiform" con gli attributi validi per tutti i browser; in testa al file, però, usate questa riga per importare un secondo foglio di stile esterno contenente altri attributi validi per i browser più avanzati:
@import url('secondo_stile.css');
Concludo la parte relativa alla grafica dei form con un'ulteriore personalizzazione riguardante, questa volta, i bottoni submit. È possibile creare una sorta di "rollover" sui bottoni del form con l'aiuto congiunto di javascript e css.
La prima cosa da fare è creare due classi, molto simili nel testo, ma differenti nei colori.
Ad esempio, tra i tag <head> della pagina, inseriremo quanto segue:
<style type="text/css">
/* importiamo un css esterno */
@import url('stile.css');
/*impostiamo la prima classe */
.campiform {
width: 55mm;
font-family: verdana, tahoma, arial;
color: red;
font-size: 10px;
}
/*impostiamo la seconda classe */
.campiform2 {
width: 55mm;
font-family: verdana, tahoma, arial;
color: white;
font-size: 10px;
}
</style>
Il css esterno invece conterrà quanto segue:
.campiform {
border-style: solid;
border-color: #006699;
border-width: 1;
background: #f0f0f0;
}
.campiform2 {
border-style: solid;
border-color: #333333;
border-width: 1;
background: #c6c6c6;
}
Il bottone submit, sarà così impostato:
<form name="saibal" action="....." method="post">
<input name="prova" type="text" size="25" class="campiform">
<input type="submit" name="submit" value="Clicca & Godi" class="campiform" onMouseOver="this.className='campiform2'" onmouseOut="this.className='campiform'">
</form>
È semplice da notare l'aggiunta fatta:
onmouseover="this.className='campiform2'" onmouseout="this.className='campiform'"
Con questa semplice riga impostiamo la classe da utilizzare sul bottone in base al comportamente del mouse: allo stato normale viene utilizzata la prima classe; se il puntatore va sopra il bottone viene usata la seconda classe; una volta che il mouse si è allontanato ritorniamo alla classe iniziale. A voi lascio il divertimento di giocare un po' con la fantasia.