Sfondo per mezzo dei CSS

2.44

Tutti gli attributi del tag <body> che sono stati illustrati fino a questo punto (ad eccezione dell’attributo lang) sono utilizzati per alterare aspetti relativi al layout della nostra pagina HTML. Come evidenziato in questo esempio di markup:

 
<body leftmargin="0" topmargin="0" background="imgs/sfondo00006.gif" bgcolor="#66CCFF" lang="it"> Il nostro testo. </body>
 

Si può notare che il layout e il contenuto sono combinati. In particolare, gli attributi background e bgcolor sono persino deprecati nelle specifiche del W3C, il che significa che presto saranno obsoleti.

In un approccio di impaginazione basato su fogli di stile, è fondamentale separare l’aspetto visivo dal contenuto effettivo. Di conseguenza, il nostro tag body sarà ridotto a qualcosa di più essenziale, come:

 
<body lang="it">
 

Nel frattempo, le regole che definiscono come presentare lo sfondo saranno collocate in una sezione separata del documento.

Le istruzioni dettagliate su come configurare lo sfondo con i CSS sono esplicate in modo approfondito nella corrispondente lezione della guida ai CSS.

I fogli di stile sono strumenti estremamente potenti, come evidenziato nel link menzionato in precedenza, che mostra la possibilità di fissare lo sfondo in modo che non si ripeta:

 
<body style="background-image: url(sfondo.gif); background-repeat: no-repeat;">
 

Questa sintassi funziona efficacemente anche con Netscape 4.x, come dimostrato nella pagina di esempio.

In alternativa, è possibile “fissare lo sfondo” in modo che il contenuto della pagina scorra sopra di esso. La sintassi per questa modalità è la seguente:

 
<body style="background-image: url(sfondo.gif); background-attachment: fixed;" >
 

CSS checkbox style: la tecnica di base

Gli esempi che andremo via via analizzando e che sono disponibili in allegato per il download condividono l’approccio di base. Sono infatti tutti fondati sul cosiddetto ‘checkbox hack’, argomento cui abbiamo dedicato nei mesi scorsi un articolo che va considerato rispetto al tema di questo un fondamentale prerequisito. Per non appesantire questo articolo con inutili ripetizioni, ad esso rimandiamo per i dettagli tecnici.

Altra lettura vivamente consigliata è quella della lezione dedicata ai selettori di relazione della guida CSS3.

La prima applicazione di questo semplice trucchetto alla personalizzazione di checkbox e radio button è stata presentata in un tutorial di CSS Ninja. Tutte le varianti che vedremo nel nostro articolo e quelle che potrete rintracciare in rete sono di fatto derivazioni dell’esperimento di Ryan Seddon. Cerchiamo dunque di comprendere la tecnica di base.

Essenzialmente, il procedimento si compone di tre fasi:

  1. nel markup HTML si inserisce un input (checkbox o radio) con una label associata;
  2. si nascondono i checkbox e radio button standard, ovvero quelli che presentano l’aspetto caratteristico di ciascun sistema operativo;
  3. si sostituiscono i controlli iniziali con controlli personalizzati nella grafica che nel loro funzionamento emulano i checkbox e i radio button.

Perché tutto possa funzionare è necessario strutturare il markup in un modo preciso. Tutti i nostri esempi hanno perciò questa configurazione nel codice HTML:

 

<input type="checkbox" id="html" value="HTML">
<label for="html">HTML</label>

 

Il checkbox o il radio button devono precedere immediatamente la label. Quest’ultima va associata all’input corrispondente tramite l’attributo for, che assume come valore l’id dell’input stesso.

Leggi Come personalizare e rendere accessibili Checkbox e Radio buttons.

 

Usare immagini per personalizzare i controlli Radio button

Le varianti che d’ora in poi analizzeremo possono essere suddivise in due categorie: quelle che sostituiscono i controlli originali con immagini e quelle che sfruttano il contenuto generato dei CSS. Iniziamo dalla prima.

La tecnica che usiamo nella prima demo è tra le più semplici.

Questo è il markup HTML:

 

<form action="">
<h2>Checkbox</h2>
<p>
<input type="checkbox" id="html" value="HTML">
<label for="html">HTML</label>
</p>
<p>
<input type="checkbox" id="css" value="CSS">
<label for="css">CSS</label>
</p>
<p>
<input type="checkbox" id="javascript" value="Javascript">
<label for="javascript">Javascript</label>
</p>
<h2>Radio button</h2>
<p>
<input type="radio" id="java" name="linguaggi" value="Java">
<label for="java">Java</label>
</p>
<p>
<input type="radio" id="php" name="linguaggi" value="PHP">
<label for="php">PHP</label>
</p>
<p>
<input type="radio" id="xml" name="linguaggi" value="XML">
<label for="xml">XML</label>
</p>
</form>

 

Nel CSS procediamo prima di tutto a nascondere i controlli standard:

 

input[type='radio'],
input[type='checkbox'] {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
}

 

Per rispettare il più possibile l’accessibilità, qui e in tutte le demo, usiamo questa soluzione basata sulla proprietà clip al posto di display:none.

I controlli nascosti saranno sostituiti con un’immagine iniziale (‘start.png’) che rappresenta i controlli disattivati. Sarà applicata come sfondo della label:

 

input[type='radio'] + label,
input[type='checkbox'] + label {
margin: 0;
padding: 2px 0 0px 24px;
cursor: pointer;
background: url('start.png') left center no-repeat;
}

 

 

Padding sul checkbox CSS

Oltre alla riga per la proprietà background, è importante quella per il padding. Per lasciare spazio all’immagine/sfondo, infatti, dovremo usare un padding sinistro adeguato. Il padding sugli altri lati (specie superiore e inferiore) andrà sistemato per ottenere una resa cross-browser consistente rispetto all’allineamento e al posizionamento.

 

Il cursore sarà di tipo pointer perché l’area è cliccabile.

Ci siamo quasi. Dobbiamo ora emulare il comportamento di checkbox e radio button. Come? Quando clicchiamo e i controlli passano allo stato :checked, l’immagine di sfondo iniziale della label sarà sostituita con quelle specifiche che sceglieremo per i radio button e per i checkbox:

 

input[type='radio']:checked + label {
background-image: url('radiobutton.png');
}
input[type='checkbox']:checked + label {
background-image: url('checkbox.png');
}

 

Tutto qui. Dobbiamo solo chiarire un aspetto importante, quello della compatibilità sui vari browser.

L’esempio funziona come è stato concepito su tutti i browser più recenti, compreso IE9. IE7 e IE8, però, non supportano la pseudoclasse :checked. Abbiamo due modi per risolvere:

  1. usare una libreria Javascript come Selectivizr per estendere il supporto della pseudoclasse su questi browser;
  2. adottare una strategia di graceful degradation.

Per implementare il tutto è sufficiente comporre tutte le dichiarazioni CSS che riguardano la personalizzazione dei controlli in questo modo:

 

p:not(#foo) > input[type='radio'],
p:not(#foo) > input[type='checkbox'] {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
}
p:not(#foo) > input[type='radio'] + label,
p:not(#foo) > input[type='checkbox'] + label {
[...]
}
[...]

 

Dato che IE7 e IE8 non supportano nemmeno la pesudoclasse :not, non interpreteranno le regole precedute da p:not(#foo) >. Questo piccolo snippet va adeguato al vostro markup. Nel nostro caso si è usato p perché gli input sono inseriti in un paragrafo. Se li racchiudete in un div scriverete:

 

div:not(#foo) > input[type='radio']

 

Quindi: si prende l’elemento che contiene gli input, si associa ad esso la pseudoclasse :not, si usa come valore un id non usato in nessuna parte della pagina (nell’esempio #foo, ma può essere pure #blahblahblah). Tutti gli esempi usano questa tecnica.

Per implementare il tutto è sufficiente comporre tutte le dichiarazioni CSS che riguardano la personalizzazione dei controlli in questo modo:

p:not(#foo) > input[type='radio'],
p:not(#foo) > input[type='checkbox'] {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
}
p:not(#foo) > input[type='radio'] + label,
p:not(#foo) > input[type='checkbox'] + label {
[...]
}
[...]

Dato che IE7 e IE8 non supportano nemmeno la pesudoclasse :not, non interpreteranno le regole precedute da p:not(#foo) >. Questo piccolo snippet va adeguato al vostro markup. Nel nostro caso si è usato p perché gli input sono inseriti in un paragrafo. Se li racchiudete in un div scriverete:

div:not(#foo) > input[type='radio']

Quindi: si prende l’elemento che contiene gli input, si associa ad esso la pseudoclasse :not, si usa come valore un id non usato in nessuna parte della pagina (nell’esempio #foo, ma può essere pure #blahblahblah). Tutti gli esempi usano questa tecnica.

Usare gli sprite

Nella prima demo abbiamo usato per implementare la tecnica tre immagini singole come sfondo. Nulla vieta di usare uno sprite come avviene nel secondo esempio:

Figura 5 – Sprite con i vari stati dei controlli
screenshot

La differenza con la prima tecnica consiste nel fatto che quando i controlli sono attivati non si modifica l’immagine di sfondo, ma la posizione dello sfondo in base alla configurazione dello sprite usando la proprietà background-position:

Figura 6 – Coordinate dello sprite
screenshot

Questo il codice CSS (nell’esempio abbiamo sfruttato solo alcuni stati):

 

p:not(#foo) > input[type='checkbox'] + label {
background: url('sprite.png') 0 0;
}
p:not(#foo) > input[type='checkbox']:checked + label {
background-position: 0 -60px;
}
p:not(#foo) > input[type='radio'] + label {
background: url('sprite.png') 0 -120px;
}
p:not(#foo) > input[type='radio']:checked + label {
background-position: 0 -180px;
}

 

Adoperando gli sprite si guadagna su un versante (una sola immagine invece che diverse), ma si deve porre più attenzione all’allineamento tra la label e il controllo. Ecco la regola che abbiamo dovuto scrivere per posizionare e allineare al meglio l’immagine/sfondo della label rispetto al testo:

 

p:not(#foo) > input[type='checkbox'] + label, /* Stili per le label */
p:not(#foo) > input[type='radio'] + label {
display: inline-block; /* Display */
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; /* Border-box */
width:30px; /* Larghezza della label = all'immagine */
height:30px; /* Altezza della label = all'immagine */
padding: 8px 0 6px 30px; /* Padding per lasciare spazio allo sfondo (a sinistra) e per posizionare al meglio il testo rispetto al controllo */
cursor:pointer; /* Imposta il cursore */
}

 

I commenti al codice sono sufficienti per rendere chiara la funzione di ciascuna regola.

La questione del posizionamento e dell’allineamento è in effetti uno degli aspetti più insidiosi da affrontare sfruttando questa tecnica (ma in generale nella strutturazione dei form con i CSS). Non solo si deve giocare quasi sempre a livello di pochi pixel, ma ci si scontra sovente con piccole inconsistenze nella resa tra i vari browser che rendono necessario testare sempre con cura per evitare differenze macroscopiche.

Nello specifico della tecnica di cui si parla in questo articolo, molte soluzioni reperibili in rete usano uno span aggiuntivo all’interno della label nel markup HTML come appoggio per i CSS, con la finalità di rendere meno complicata la gestione dei controlli e del loro posizionamento. Il codice HTML assume tipicamente questa forma:

 

<input type="checkbox" id="html" value="HTML">
<label for="html"><span></span> HTML</label>

 

Su questo approccio è basato il terzo dei nostri esempi.

Lascia un commento