Best Practices CSS: l’organizzazione dei fogli di stile

Quando ci occupiamo della presentazione di un'applicazione o di un sito Web molto del lavoro riguarda la grafica e la definizione dei fogli CSS. Spesso ci concentriamo solamente sui dettagli, ovvero sulla valorizzazione delle proprieta CSS, scegliendo con cura ogni selettore ed ogni regola del foglio di stile. Occuparsi della presentazione non si limita a questo aspetto, ma dovrebbe considerare anche questioni architetturali, come ad esempio: preferiamo inserire tutte le regole CSS in un unico foglio di stile esterno o frammentarle tra fogli diversi? Dobbiamo evitare i fogli di stile interni o esistono eccezioni? La definizione delle regole CSS dev'essere gestita in modo manuale o puo interagire con JavaScript? Chiaramente non esistono risposte universali a queste domande, ma le risposte dipendono dai requisiti specifici del progetto su cui stiamo lavorando.

Quando ci occupiamo della presentazione di un’applicazione o di un sito Web molto del lavoro riguarda la grafica e la definizione dei fogli CSS. Spesso ci concentriamo solamente sui dettagli, ovvero sulla valorizzazione delle proprietà CSS, scegliendo con cura ogni selettore ed ogni regola del foglio di stile. Occuparsi della presentazione non si limita a questo aspetto, ma dovrebbe considerare anche questioni architetturali, come ad esempio: preferiamo inserire tutte le regole CSS in un unico foglio di stile esterno o frammentarle tra fogli diversi? Dobbiamo evitare i fogli di stile interni o esistono eccezioni? La definizione delle regole CSS dev’essere gestita in modo manuale o può interagire con JavaScript?

Chiaramente non esistono risposte universali a queste domande, ma le risposte dipendono dai requisiti specifici del progetto su cui stiamo lavorando. Possiamo comunque suggerire alcune metodologie che sono state individuate come best practices, ovvero “buone pratiche” diffuse sul Web per consuetudine. Inizieremo discutendo alcune soluzioni pratiche e concluderemo osserveremo che le soluzioni rientrano nell’ambito di una metodologia nota come Progressive Enhancement. Procedendo in questo modo ci ispiriamo ad un metodo didattico che risale agli antichi babilonesi: prima la pratica e poi la teoria, intesa come sintesi della pratica.

 Evitare i duplicati

Il primo suggerimento dovrebbe essere ben noto agli esperti del settore. Molte volte, quando assegniamo una certa proprietà CSS ad un elemento HTML, dobbiamo “armonizzarlo” con gli elementi circostanti. Ad esempio, se un certo box contenitore presenta uno sfondo di colore blu, molto probabilmente il font al suo interno sarà chiaro (meglio ancora bianco). In alcuni casi questa “armonizzazione” diventa un’uguaglianza. Ad esempio, se l’intera pagina usa un certo tipo di colore o font, molto probabilmente questo colore (o font) verrà di utilizzato anche dagli elementi interni alla pagina. Tutte le volte che ciò accade dobbiamo evitare di definire la stessa proprietà più di una volta. Vediamo un esempio concreto

Qui sopra abbiamo due regole CSS che sono “armonizzate” tra loro, perché devono usare lo stesso colore. Il codice qui sopra è piuttosto brutto: ogni volta che cambiamo il colore dobbiamo ricordarci di editare entrambe le regole. Apparentemente si potrebbe pensare che basti usare la funzione “sostituisci tutto” dell’editor, ma ciò non è sempre vero. Se il foglio di stile contiene parecchie centinaia di righe, andare a sostituire tutte le stringhe “blue” con qualcos’altro è piuttosto pericoloso. In questi casi è molto meglio scrivere le regole CSS aggregando le proprietà comuni in un’unica regola:

Sicuramente più facile da mantenere nel tempo.

Frammentazione del foglio di stile

Frammentazione del foglio di stile

Cambiamo ora prospettiva, passando agli aspetti architetturali dei fogli di stile. Una pratica piuttosto diffusa consiste nel frammentare il foglio di stile in file più piccoli, ciascuno relativo al gruppo di pagine associato ad una certa entità. Supponiamo ad esempio che l’applicazione debba gestire clienti, prodotti, spedizioni, magazzino eccetera. Supponiamo poi che ciascuna di queste entità debba essere presentata con una grafica e un look & feel diverso. Avremo così una grafica per i clienti, un’altra grafica per i prodotti eccetera. Se ciascuna di queste entità richiede, ad esempio, 1000 righe di codice CSS per essere caratterizzata, il foglio di stile complessivo potrebbe essere lungo parecchie migliaia di righe. Una scelta possibile consiste nel frammentare questo file in parte diverse: avremmo così un foglio di stile per i clienti, uno per i prodotti eccetera.

Questa scelta è piuttosto critica. In alcuni casi la soluzione è vantaggiosa, in altri casi potrebbe risultare svantaggiosa. Consigliamo quindi di non applicarla a scatola chiusa, ma di ponderare sempre le diverse possibilità. Vediamo quali sono gli aspetti da prendere in considerazione per capire se la frammentazione dei fogli di stile fa al caso nostro. Innanzitutto stimiamo quanto potrebbe essere grande il foglio stile complessivo. Se un unico foglio di stile valido per tutte le entità dell’applicazione risultasse pari a 50KB o 100KB possiamo ancora valutare di lasciarlo così com’è. Ricordiamo infatti che i fogli stile vengono solitamente “cachati” dal browser, per cui il foglio di stile verrà probabilmente scaricato solo una volta da parte dell’utente: scaricare un centinaio di KB una tantum non è sicuramente un problema.

Se il foglio CSS è particolarmente grande (oltre i 100KB), oppure se dobbiamo dividerlo in files diversi per altre esigenze (ad esempio perché utilizziamo un framework), allora possiamo decidere tra due possibilità.

  • Header specifici : per definire il foglio di stile all’interno della tag HTML head probabilmente dovremo usare un header specifico per ciascuna sezione. Avremo così un header per i clienti, diverso dall’header dei prodotti. Si capisce che tale pratica potrebbe essere un’arma a doppio taglio, perché costringe a mantenere un header per ciascun foglio di stile. Questo modo di lavorare può risultare conveniente se siamo sicuri che le diverse entità siano davvero indipendenti le une dalle altre, per cui il gioco vale la candela.
  • Inclusione a run-time: in altri casi possiamo decidere di usare un unico header per l’intera applicazione, che sia però in grado di caricare il giusto foglio di stile CSS a seconda delle esigenze. Questo può essere realizzato facilmente con JavaScript. Anche in questo caso esiste un rovescio della medaglia, che approfondiamo nella prossima pagina.

Inclusione a run-time

Inclusione a run-time

Approfondiamo la possibilità di includere un foglio di stile CSS a run-time, ovvero senza includerlo all’interno della tag head. Questo può essere fatto in modi diversi: una delle soluzioni più semplici è quella di usare JavaScript. Esiste però un potenziale rischio: alcuni browser potrebbero non permettere l’operazione, vuoi perché troppo vecchi (ormai piuttosto improbabile), vuoi perché l’utente ha disabilitato JavaScript per motivi di sicurezza. Quest’ultimo scenario non è trascurabile, perché alcune aziende impongono di disabilitare JavaScript come policy aziendale. Il codice in questione è il seguente

Siccome il codice viene eseguito durante il caricamento la pagina, anche se JavaScript funziona correttamente l’utente potrebbe notare un cambiamento nella presentazione. In altre parole l’utente vedrebbe prima aprirsi la pagina in un certo modo (cioè senza il CSS che verrà caricato dinamicamente), e dopo una frazione di secondo vedrebbe l’aspetto della pagina cambiare sotto i propri occhi.

Ecco che entra in ballo la teoria suggerita dal Progressive Enhancement. La metodologia può essere riassunta in tre punti:

  • Presentazione minimale: la nostra pagina deve essere fruibile, seppur in modo scarno e minimale, anche nei browser che non utilizzano JavaScript. Nella pratica ciò significa che i contenuti devono essere visualizzati comunque. Successivamente, se possibile, possiamo arricchire (enhance) i contenuti dal punto di vista grafico o funzionale.
  • Browser non aggiornato : il codice JavaScript deve funzionare anche se l’utente non ha aggiornato il browser e alcune librerie.
  • Link esterni: se la pagina richiede particolari librerie esse vanno caricate come link esterni alla pagina e mai incluse in essa. In questo modo, se il browser non supporta delle librerie o tecnologie, garantiamo comunque la fruizione dei contenuti o del servizio.

Vediamo come applicare la metodologia nella pratica. Supponiamo di voler includere alcuni fogli di stile a run-time, usando il codice JavaScript visto sopra. In questo caso dobbiamo assicurarci che la pagina sia utilizzabile anche senza il foglio specifico che carichiamo via JavaScript. In altre parole deve esserci un foglio CSS di default, probabilmente comune all’intera applicazione, che si occupa di garantire almeno il layout. Ciò suggerisce, ad esempio, di specificare il layout dei componenti in un foglio comune a tutte le pagine e andare poi a caratterizzare la presentazione nei fogli specifici (quelli caricati via JavaScript).

La metodologia Progressive Enhancement suggerisce anche un modo di risolvere il problema della presentazione discontinua della pagina, ovvero il cambiamento che l’utente percepisce nell’istante in cui carichiamo dinamicamente un nuovo foglio di stile. Consideriamo ad esempio la seguente soluzione realizzata usando jQuery:

In questo modo il codice JavaScript che si occupa di caricare i fogli CSS necessari alla pagina viene eseguito solamente mentre gli elementi in questione (nel nostro esempio content, nav e menu) sono nascosti. Solo alla fine andiamo a visualizzare nuovamente gli elementi che ci interessano.

Questo modo di lavorare funziona anche se il browser non permette l’esecuzione di JavaScript, perché in tal caso gli elementi HTML non verrebbero neppure nascosti e quindi resterebbero visibili. L’esempio qui sopra è volutamente semplificato al massimo, l’importante è cogliere la relazione tra teoria e pratica: abbiamo garantito una presentazione minimale della pagina anche quando il browser non è aggiornato, e l’abbiamo fatto usando una libreria esterna (cioè jQuery) per nascondere i contenuti mentre la pagina viene caricata. Le parole scritte in corsivo sono esattamente l’applicazione dei principi del Progressive Enhancement. L’esempio dovrebbe mostrare come sia possibile passare dalla teoria alla pratica qualsiasi sia la situazione da affrontare, sia essa pratica (dettagli di implementazione) o architetturale (design dell’applicazione).