In alcuni articoli precedenti ci siamo occupati di analizzare tutti i tipi di selettori presenti nella specifica del CSS3 fornendone per ognuno la compatibilità con le varie versioni dei vari browser. Abbiamo quindi suddiviso i selettori in quattro categorie:
- I selettori di attributo nei CSS3
- Le pseudo-classi strutturali
- Altre pseudo-classi
- I selettori combinatori nei CSS3
Il problema principale dell'utilizzo di queste nuove proprietà è la compatibilità stessa che ne impedisce l'utilizzo per progetti che richiedono il pieno supporto anche per versioni di browser datate. Internet Explorer nella versione 6 non è compatibile con nessuno dei selettori avanzati analizzati negli articoli e, considerata la sua larga diffusione, questo può risultare un grosso problema nella progettazione di applicazioni cross-browser. Molti dei nuovi selettori, poi, non risultano essere compatibili neppure con le ultime versioni dei browser di casa Microsoft e con le versioni 2 e 3 di Firefox.
Vedremo in questo articolo come ovviare alle incompatibilità di tali browser ed estendere il supporto ai selettori CSS3 affidandoci a Javascript, e più precisamente, ad uno dei framework più popolari, jQuery. Per chi non conoscesse le potenzialità del noto framework, si può fare riferimento alla guida di Marco Solazzi pubblicata su HTML.it.
I selettori di attributo
Come possiamo notare dalla tabella di compatibilità, per questo genere di selettori il problema si presenta solo con la versione 6 di Internet Explorer. La soluzione alla compatibilità è piuttosto semplice e richiede davvero pochissime righe di codice. Tale soluzione, inoltre, è uguale per ogni selettore appartenente a questa categoria.
La soluzione consiste nel creare una classe CSS che contiene gli stessi attributi assegnati al selettore e assegnarla tramite Javascript al caricamento della pagina.
Prendiamo uno degli esempi utilizzati nell'articolo sui selettori di attributo e rendiamolo compatibile anche per IE6 utilizzando jQuery.
Dato il seguente codice HTML
<a title="Lorem Ipsum" href="#">Lorem Ipsum</a>
avevamo utilizzato la seguente regola CSS per assegnare uno stile a tutti i link che contenevano l'attributo title
al loro interno:
a[title] { color: blue; text-decoration: underline; }
Per rendere cross-browser la precedente regola è sufficiente creare una classe che contiene le stesse proprietà del selettore precedente ed assegnarla dinamicamente con jQuery.
Il codice CSS diviene, quindi, il seguente:
a[title] { color: blue; text-decoration: underline; }
.selector { color: blue; text-decoration: underline; }
Facciamo attenzione a mettere in righe diverse le due regole altrimenti IE6 non la interpreterà.
Il codice Javascript di cui abbiamo bisogno, invece, è il seguente:
$(document).ready(function(){
$('a[title]').addClass('selector');
});
Dato che è il primo esempio dell'articolo, analizziamo un attimo il codice Javascript per coloro che non sono molto esperti di jQuery. La prima e la terza riga servono semplicemente a "catturare" l'evento ready
del documento, ovvero il momento in cui la pagina è caricata. Tutto il codice contenuto tra queste righe viene eseguito nel momento in cui la pagina viene caricata. La riga 2 dell'esempio, invece, assegna la classe selector
al selettore a[title]
. jQuery garantisce il funzionamento dei suoi selettori con tutte le versioni dei browser quindi abbiamo la garanzia che il nostro selettore verrà identificato dal Javascript, a questo punto non ci resta che assegnare la classe creata precedentemente nel CSS.
Per evitare malfunzionamenti o interpretazioni strane, quando possibile, è più indicato eseguire il codice Javascript all'interno di commenti condizionali appositi per i browser a cui è destinato il codice. In questo caso, quindi, è consigliato inserire tale codice all'interno di un commento condizionale per Internet Explorer 6 e inferiore.
Possiamo vedere tutto in azione nell'esempio completo.
L'esempio visto in precedenza è del tutto simile per tutti i restanti selettori di attributo, senza bisogno di particolari accorgimenti.
Le pseudo-classi strutturali
Per questa categoria di selettori sono molti di più i browser che hanno problemi di compatibilità. Internet Explorer in tutte le sue versioni non ne supporta nessuno e, anche Firefox, nelle sue versioni più datate presenta qualche problema.
La soluzione adottata per la classe di selettori precedente, può essere utilizzata anche per gestire anche le pseudo-classi strutturali.
Bisogna però fare alcune precisazioni riguardo alcuni selettori non supportati nativamente dal framework. Fortunatamente il loro supporto può essere esteso attraverso dei plugin aggiuntivi.
E:nth-last-child()
può essere integrato grazie ad un plugin creato da Ben Alman. Il plugin è scaricabile a questo indirizzo.
Per aggiungere il supporto dei selettori:
nth-of-type()
nth-last-of-type()
first-of-type
last-of-type
only-of-type
è possibile scaricare il plugin moreSelectors disponibile al seguente indirizzo.
Vediamo un esempio con nth-child()
ricordando che per le altre pseudo-classi sopra elencate, il funzionamento è del tutto simile. Questa volta non possiamo utilizzare commenti condizionali dato che l'incompatibilità non è solo con Internet Explorer.
Utilizziamo come esempio una tabella HTML come la seguente:
<table>
<tr><th>Cognome</th><th>Nome</th></tr>
<tr><td>Rossi</td><td>Mario</td></tr>
<tr><td>Bianchi</td><td>Giorgio</td></tr>
<tr><td>Esposito</td><td>Luca</td></tr>
<tr><td>Verdi</td><td>Michele</td></tr>
<tr><td>Russo</td><td>Francesco</td></tr>
</table>
Volendo dare un colore di background diverso alle righe pari, abbiamo bisogno di due regole CSS; una per i browser compatibili, una da assegnare attraverso jQuery.
tr:nth-child(even) { background-color: #DFFFFB; }
.nthchild { background-color: #DFFFFB; }
A questo punto il codice Javascript è del tutto simile a quello utilizzato nell'esempio dei precedenti selettori.
$(document).ready(function(){
$("tr:nth-child(even)").addClass('nthchild');
});
L'esempio è disponibile al seguente link.
Ci sono alcuni selettori aggiuntivi forniti da jQuery che facilitano l'utilizzo di nth-child()
, i più importanti sono:
- :even
- :odd
- :first-child
Per una completa visione dei selettori forniti da jQuery, si può fare riferimento alla documentazione ufficiale.
Altre pseudo-classi
I problemi di compatibilità per questi selettori appartengono prettamente ad Internet Explorer, eccenzion fatta per il checked
che non è supportato anche da Opera.
La soluzione per tutti è del tutto identica a quella utilizzata per gli esempi precedenti. L'unica pseudo-classe da analizzare è target
per cui non è stato implementato un selettore dedicato in jQuery ma è gestito l'evento ad essa associato.
Prendiamo l'esempio visto nell'articolo relativo, disponibile su questa pagina. Dobbiamo creare un piccolissimo script che, al click su uno dei link della lista puntata, assegna una classe target al div corrispondente.
Innanzitutto creiamo una classe .target
del tutto simile a quella corrispondente e compatibile con i browser. A questo punto utilizziamo jQuery, ricordandoci di includere il codice all'interno dei commenti condizionali per IE6.
$(document).ready(function(){
if(window.location.hash)
$('div#'+window.location.hash).addClass('target');
//gestione evento click
$('ul li a').click(function(event){
var $target = $(event.target);
var $div = $target.attr('href');
$('div').removeClass('target');
$('div'+$div).addClass('target');
});
});
La prima parte dello script verifica che sia presente l'hash al caricamento della pagina e, in caso positivo, assegna da principio la classe al div corrispondente. La seconda parte si attiva al click su uno dei link e va a simulare il target del CSS3 assegnando dinamicamente la classe.
Il nuovo esempio è disponibile in questa demo.
I selettori combinatori nei CSS3
Figura 4 - Tabella di compatibilità
L'ultima categoria di selettori non richiede particolare lavoro di adattamento a tutti i browser, è sufficiente utilizzare la tecnica degli esempi precedenti.
Riprendiamo uno degli esempi dati per l'articolo relativo integrandone la compatibilità con Internet Explorer 6. Anche in questo caso è sufficiente realizzare una classe con le stesse proprietà ed utilizzare il seguente codice jQuery:
$(document).ready(function(){
$('h1 ~ h2').addClass('adiacent');
});
Il nuovo esempio è disponibile su questa pagina.
Tutti gli esempi visti nell'articolo sono disponibili per il download.