CSS (Cascaded Style Sheets)

Introduzione

Una volta le pagine web erano costituite solo dal codice HTML, in cui erano inseriti sia il contenuto che la descrizione dell'aspetto delle pagine. Questo modello aveva però molti svantaggi, per superare i quali furono introdotti i CSS (Cascaded Style Sheet, in italiano Fogli di stile).

Grazie ai fogli di stile, è possibile separare nettamente il contenuto della pagina (testi, link, immagini, video, ecc.) dal suo aspetto (formattazione, dimensioni, posizionamento, tipo di layout, ecc.). Il contenuto è descritto da un file HTML, mentre l'aspetto è definito in un file CSS.

Per comprendere meglio il concetto, conviene ricorrere ad un esempio. Vediamo come la stessa pagina web possa apparire diversa solo se la si collega a due CSS diversi.

Selettori e prime proprietà CSS

Un foglio di stile è un file contenente una collezione di regole definite secondo questa sintassi:

selettore {
  proprietà_1: valore;
  proprietà_2: valore;
  proprietà_3: valore;
  ...
}

Che cos'è un selettore?

Il selettore serve a definire la parte della pagina HTML a cui si devono applicare le regole di formattazione contenute nelle parentesi graffe che lo seguono.

Il selettore più semplice che potremo utilizzare è quello che corrisponde ad un tag dell'HTML; le regole di formattazione, in questo caso, si applicheranno a tutti gli elementi della pagina del tipo corrispondente al tag. Facciamo un esempio.

Consideriamo questo codice HTML, che inserisce nella pagina un titolo, un sottotitolo e due paragrafi:

<body>
  <h1>Chapter I</h1>
  <h2>Down the Rabbit-Hole</h2>
  <p>Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice 'without pictures or conversations?'</p>
  <p>So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.</p>
  <p>There was nothing so VERY remarkable in that; nor did Alice think it so VERY much out of the way to hear the Rabbit say to itself, 'Oh dear! Oh dear! I shall be late!' (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-POCKET, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.</p>
  <p>In another moment down went Alice after it, never once considering how in the world she was to get out again.</p>
  <p>The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well.</p>
</body>

Vediamo come appaiono nella pagina questi elementi se per essi non si definisce nessuna regola CSS:

Come si vede, il browser fornisce comunque, anche in assenza di un foglio di stile, un minimo di formattazione che consenta di distinguere il titolo di primo livello dal sottotitolo e dai normali paragrafi di testo. In pratica, il browser possiede alcune regole di stile "di default", che applica in assenza di stili definiti dal creatore della pagina web.

Come prima semplice regola di stile, applichiamo al titolo di primo livello un diverso colore del testo, ad esempio arancione. La proprietà da utilizzare per impostare il colore del testo si chiama color. Ecco il codice CSS con cui ottenerlo:

h1 {
  color: orange;
}

Ed ecco lo stile applicato all'esempio:

Ora applichiamo anche un colore di sfondo all'elemento h1. La proprietà da utilizzare per impostare il colore di sfondo si chiama background-color:

h1 {
  color: orange;
  background-color: green;
}

Ecco cosa otteniamo:

Bisogna ammettere che l'effetto ottenuto non è un gran che. Forse sarebbe meglio applicare il colore di sfondo all'intera pagina. Per fare questo, dobbiamo impostare la proprietà background-color dell'elemento body. Contemporaneamente, impostiamo come colore del testo dell'intera pagina il bianco:

body {
  background-color: green;
  color: white;
}

h1 {
  color: orange;
}

Ecco il risultato:

Possiamo già fare una prima osservazione interessante: l'impostazione del bianco come colore del testo di tutta la pagina (poiché applicato all'elemento body) viene "superata" dall'impostazione di un altro colore per l'elemento h1, che pure è contenuto all'interno del tag body. E' proprio qui che emerge il significato di "fogli di stile a cascata": quando per lo stesso elemento sono fissate due regole, la regola definita per il selettore più specifico (nel nostro caso h1) sovrascrive la regola definita per il selettore più generico (nel nostro caso body).

E' ora di imparare qualche altra proprietà CSS. Lavoriamo un po' sul testo.

Innanzitutto: scegliamo un font diverso da quello predefinito. Ecco i nomi di alcuni font molto utilizzati: Verdana, Tahoma, Arial, ecc. Noi utilizzeremo Georgia, molto adatto al nostro caso, visto che stiamo pubblicando un capitolo di un libro. La proprietà da impostare è font-family.

Inoltre, modifichiamo l'aspetto del testo del sottotitolo, impostandone le dimensioni con la proprietà font-size, il "peso" (normale o grassetto) con la proprietà font-weight e lo "stile" (normale o corsivo) con la proprietà font-style.

Ecco il CSS completo:

body {
  background-color: green;
  color: white;
  font-family: Georgia;
}
h1 {
  color: orange;
}
h2 {
  font-size: 20px;
  font-weight: normal;
  font-style: italic;
}

Ed ecco come si presenta ora la pagina:

A questo punto possiamo notare come leggere un testo che occupi l'intera larghezza della pagina sia piuttosto scomodo. Nella visualizzazione di pagine web su schermi molto larghi, si tende ad utilizzare solo una parte della larghezza per il testo, lasciando dello spazio ai lati (a destra, a sinistra o su entrambi i lati). Questo spazio, tra l'altro, può essere sfruttato per l'inserimento di menù di navigazione, banner pubblicitari, ecc.

La proprietà che definisce la larghezza di un elemento si chiama width. Noi imposteremo quella dell'elemento body, utilizzando inizialmente una larghezza fissa, espressa in pixel:

body {
  background-color: green;
  color: white;
  font-family: Georgia;
  width: 500px;
}

Ecco il risultato:

Per "centrare" il contenuto, lasciando un uguale margine a destra e a sinistra, possiamo utilizzare la proprietà margin, impostandola sul valore auto:

body {
  background-color: green;
  color: white;
  font-family: Georgia;
  width: 500px;
  margin: auto;
}

Ecco ciò che si ottiene:

Torneremo più avanti sulla proprietà margin. Per ora, basti sapere che il margine di un elemento è la distanza tra il suo bordo e quello degli elementi limitrofi. Si può definire l'entità di ciascun margine (superiore, destro, inferiore, sinistro), oppure definire tutti i margini contemporaneamente, impostando un unico valore come nell'esempio. I valori possono essere espressi in pixel o in percentuale.

Torniamo per un attimo alla proprietà width, a cui abbiamo dato un valore in pixel, quindi un valore fisso. Vediamo cosa succede se modifichiamo le dimensioni della finestra:

La figura ci consente di effettuare due osservazioni:

Si può ottenere un comportamento migliore utilizzando, per la larghezza, un valore percentuale:

body {
  background-color: green;
  color: white;
  font-family: Georgia;
  width: 60%;
  margin: auto;
}

In questo caso, un ridimensionamento della finestra provoca un adattamento del flusso del testo (che non viene tagliato) e non elimina del tutto i margini, poiché la larghezza dell'elemento body è calcolata in percentuale rispetto alle effettive dimensioni della finestra:

Menù di navigazione

A questo punto aggiungiamo dei link ai capitoli del libro, raggruppandoli in un menù di navigazione. Utilizziamo, per raggrupparli, una lista non ordinata, ossia un elemento ul (vedi Tag fondamentali dell'HTML), inserito all'inizio della sezione body:

<body>
  <ul>
    <li><a href="ChapterI.html">Chapter I</a></li>
    <li><a href="ChapterII.html">Chapter II</a></li>
    <li><a href="ChapterIII.html">Chapter III</a></li>
    <li><a href="ChapterIV.html">Chapter IV</a></li>
    <li><a href="ChapterV.html">Chapter V</a></li>
  </ul>

  <h1>Chapter I</h1>
  <h2>Down the Rabbit-Hole</h2>
  <p>Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice 'without pictures or conversations?'</p>
  <p>So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.</p>
  <p>There was nothing so VERY remarkable in that; nor did Alice think it so VERY much out of the way to hear the Rabbit say to itself, 'Oh dear! Oh dear! I shall be late!' (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-POCKET, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.</p>
  <p>In another moment down went Alice after it, never once considering how in the world she was to get out again.</p>
  <p>The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well.</p>
</body>

Vediamo come appare la pagina senza applicare nessuno stile ai nuovi elementi inseriti:

Dal momento che per raggruppare i link abbiamo utilizzato un elenco puntato, non ci stupisce che sulla pagina sia apparso proprio un elemento di questo tipo. Questa non è la barra di navigazione che vorremmo: piuttosto che link elencati dall'alto verso il basso, vorremmo dei "pulsanti" disposti orizzontalmente, uno a fianco all'altro.

Per trasformare l'aspetto della barra di navigazione, dobbiamo impostare alcune sue proprietà CSS.

Innanzitutto eliminiamo i punti elenco, impostando la proprietà list-style-type, che definisce il tipo di punti elenco da utilizzare, al valore none (nessuno):

ul {
  list-style-type: none;
}

Poi facciamo in modo che i singoli punti elenco appaiano allineati, ossia come elementi "inline" ("in linea", appunto), invece che incolonnati dall'alto verso il basso. Per far questo dobbiamo impostare la proprietà display:

ul {
  list-style-type: none;
}
li {
  display: inline;
}

Ora l'aspetto della pagina sarà il seguente:

Per far sì che l'aspetto dei link sia più simile a quello di pulsanti, eliminiamo la sottolineatura (attraverso la proprietà text-decoration)...

ul {
  list-style-type: none;
}
li {
  display: inline;
}
a {
  text-decoration: none;
}

...e aggiungiamo ad ogni elemento li uno sfondo nero (attraverso la proprietà background-color) e un bordo bianco (attraverso la proprietà border):

ul {
  list-style-type: none;
}
li {
  display: inline;
  background-color: black;
  border: solid 1px white;
}
a {
  text-decoration: none;
}

Con le proprietà impostate finora dovremmo aver ottenuto questo:

Il testo dei pulsanti è troppo vicino al bordo: la proprietà che determina la spaziatura interna tra il bordo di un elemento e il suo contenuto si chiama padding. Impostiamola per gli elementi <li>:

ul {
  list-style-type: none;
}
li {
  display: inline;
  background-color: black;
  border: solid 1px white;
  padding: 5px;
}
a {
  text-decoration: none;
}

Il colore azzurro del testo dei link è quello predefinito, che possiamo modificare attraverso la proprietà color. Questa volta, però, invece del nome del colore, utilizziamo il codice rgb.

I colori, in HTML, possono essere espressi attraverso i valori delle loro componenti rossa, verde e blu (codice rgb). Ogni componente può assumere un valore compreso tra un valore minimo pari a 0 e un valore massimo pari a 255. Un rosso acceso, ad esempio, sarà descritto da un valore massimo (255) per la sua componente rossa, e un valore minimo (0) per le altre due componenti verde e blu. Potrà quindi essere espresso così: rgb(255,0,0).

Allo stesso modo, rgb(0,255,0) rappresenterà un verde acceso, e rgb(0,0,255) un azzurro. Il bianco sarà rappresentato da tutte e tre le componenti al loro valore massimo: rgb(255,255,255); mentre il nero sarà caratterizzato da tutti valori nulli: rgb(0,0,0).

Tutti gli altri colori sono rappresentati dalle diverse combinazioni delle tre componenti: rgb(255,255,0) sarà un giallo molto chiaro, mentre rgb(255,0,255) sarà un viola con uguale componente di rosso e blu, entrambe al valore massimo; rgb(150,0,150), invece, sarà un viola più scuro (perché le due componenti rossa e blu non sono impostate al valore massimo).

Per il colore del testo dei link, scegliamo un viola tendente al blu (cioè con componente blu preponderante rispetto a quella rossa):

ul {
  list-style-type: none;
}
li {
  display: inline;
  background-color: black;
  border: solid 1px white;
  padding: 5px;
}
a {
  text-decoration: none;
  color: rgb(100,0,255);
}

Ed ecco cosa otteniamo:

Potremmo già dirci soddisfatti: con poche proprietà CSS abbiamo dato un aspetto leggibile e piacevole alla nostra pagina. Controlliamo però cosa succede se ridimensioniamo la finestra:

Ops! Che pasticcio! I pulsanti che abbiamo creato non solo "vanno a capo", ma la seconda riga si sovrappone alla prima e il pulsante "Chapter III" è stato "tagliato".

Cosa è successo?

Il problema è nell'aver definito inline gli elementi <li>, allo scopo di disporli allineati orizzontalmente invece che incolonnati l'uno sull'altro. Un elemento definito inline viene considerato come facente parte del flusso del testo. E quindi, si comporta come il testo, anche se è stato contornato da un bordo, se gli è stato dato un colore di sfondo oppure gli è stato assegnato un padding.

Riepiloghiamo: esistono due tipi di elementi:

Nella classificazione precedente, abbiamo inserito nell'una o nell'altra categoria gli elementi più utilizzati, basandoci sul loro comportamento di default. Questo comportamento, comunque, può essere modificato attraverso i CSS impostando la proprietà display ai valori inline oppure block.

Per capire meglio, ricorriamo ad un esempio. Nella pagina che segue abbiamo inserito un "esemplare" di ciascuno degli elementi HTML più utilizzati, alternandoli con del testo. Alcuni elementi "vanno a capo", altri scorrono nel flusso del testo. Ecco cosa si ottiene:

Come si vede, l'immagine (lo smile) e il link (il testo viola sottolineato alla penultima riga), essendo elementi inline, sono inseriti nel flusso del testo. Tutti gli altri elementi "vanno a capo" e prendono da soli tutto lo spazio orizzontale della finestra, non permettendo ad altri elementi di affiancarli.

Ora imponiamo che tutti gli elementi della pagina si comportino come elementi inline, attraverso la seguente regola CSS: * {
  display: inline;
}

Per imporre la regola a tutti gli elementi della pagina, abbiamo utilizzato un selettore particolare, il selettore *.

Vediamo qual è l'effetto che si ottiene:

Come previsto, tutti gli elementi scorrono uno dopo l'altro, inseriti nel flusso del testo, senza mai "andare a capo".

Ora facciamo l'esperimento opposto, trasformando tutti gli elementi in elementi block con la seguente regola:

* {
  display: block;
}

Ecco il risultato:

La maggior parte degli elementi contenuti in questa pagina di esempio si comportano come elementi block già di default, quindi in questo ultimo esempio non hanno cambiato il loro comportamento. Gli unici che l'hanno fatto sono l'immagine e il collegamento, che, essendosi trasformati in elementi block, non sono più inseriti nel flusso del testo, ma occupano una riga intera, senza essere affiancati da altri elementi né da testo.

Ora che abbiamo capito il significato di elementi di tipo block ("block elements") ed elementi di tipo inline ("inline elements"), possiamo tornare alla nostra barra del menù.

I pulsanti della barra non possono essere definiti come block elements perché li vogliamo affiancati orizzontalmente. Ma averli definiti inline elements li fa comportare come normale testo: vanno a capo quando è finito lo spazio a loro dispozione, anche se questo comporta il "taglio" del testo contenuto in un link; inoltre, il testo in essi contenuto scorre disinteressandosi dei margini, dei bordi e del padding che gli abbiamo aggiunto (per questo, nel nostro caso, i pulsanti della riga inferiore si sono sovrapposti a quelli della riga superiore).

Per fortuna, oltre alle due impostazioni inline e block, ne esiste una terza: inline-block.

Gli elementi inline-block vengono trattati come elementi block, nel senso che il loro posizionamento tiene conto di margin, border e padding. Ma, a differenza dagli elementi block, possono essere affiancati gli uni con gli altri.

Impostiamo gli elementi <li> del nostro menù come elementi inline-block:

li {
  display: inline-block;
  background-color: black;
  border: solid 1px white;
  padding: 5px;
}

Quando la finestra ha dimensioni normali tutto resta come prima. Quando invece viene ridimensionata, ecco come si dispongono i pulsanti:

Non è certo la soluzione ottimale, ma almeno non c'è più la confusione di prima. Cosa possiamo migliorare?

Innanzitutto, dobbiamo decidere se ci piace che i pulsanti si dispongano su più righe. In genere si evita di fare questa scelta; supponiamo però che a noi piaccia così. Allora cerchiamo prima di tutto di recuperare un po' di spazio allineando il bordo sinistro del contenitore dei pulsanti (cioè l'elemento <ul>) al bordo sinistro dell'elemento <body>, eliminando il rientro mostrato nella figura seguente:

Quel "rientro" può essere dovuto al margin (ossia il margine esterno al bordo dell'elemento) oppure al padding (ossia il margine interno, quello tra il bordo e il contenuto). Per scoprirlo, impostiamo (solo temporaneamente) un bordo per l'elemento <ul>:

ul {
  list-style-type: none;
  border: solid 1px white;
}

Ed ecco visualizzato il bordo appena aggiunto:

Come si vede, il "rientro" è dovuto al padding, ossia alla spaziatura interna al bordo dell'elemento. Per eliminarlo, impostiamo quindi il padding al valore zero (contemporaneamente eliminiamo il bordo che abbiamo introdotto):

ul {
  list-style-type: none;
  padding: 0;
}

Per migliorare ulteriormente l'aspetto del menù, impostiamo un margine che separi una riga dall'altra:

li {
  display: inline-block;
  background-color: black;
  border: solid 1px white;
  padding: 5px;
  margin-bottom: 5px;
}

Ecco cosa otteniamo:

Questo risultato è più che soddisfacente. Supponiamo, però, di volere pulsanti tutti della stessa larghezza, in modo che, quando si dispongono su più righe, non avvenga il disallineamento che si vede nella figura precedente.

Dopo qualche prova, la larghezza ottimale risulta essere 90px:

li {
  display: inline-block;
  background-color: black;
  border: solid 1px white;
  padding: 5px;
  margin-bottom: 5px;
  width: 90px;
}

Ecco il risultato su una finestra "larga":

...e su una finestra "stretta":

Se si desidera che il testo dei pulsanti sia centrato, si può ottenerlo assegnando il valore center alla proprietà text-align:

li {
  display: inline-block;
  background-color: black;
  border: solid 1px white;
  padding: 5px;
  margin-bottom: 5px;
  width: 90px;
  text-align: center;
}

Utilizziamo la stessa proprietà per giustificare il testo dei paragrafi (assegnandole il valore justify); oltre a questo, eliminiamo il margine che separa un paragrafo dall'altro e aumentiamo l'interlinea del testo:

p {
  text-align: justify;
  margin: 0;
  line-height: 140%;
}

Per impostare l'altezza della linea (l'interlinea), abbiamo utilizzato un valore percentuale rispetto alla dimensione del testo (il "font size").

Ed ecco (finalmente) la pagina che abbiamo realizzato: