CSS: Introduzione

Transcript

CSS: Introduzione
Laboratorio di Tecnologie Web
CSS: Introduzione
Dott. Stefano Burigat
www.dimi.uniud.it/burigat
Cascading Style Sheets (CSS) è uno standard W3C che
definisce gli aspetti di presentazione dei documenti HTML.
L'utilizzo di CSS permette un controllo preciso del layout e
dell'aspetto grafico di un documento, permette di
modificare la presentazione di un intero sito senza
modificarne minimamente il contenuto, rende più semplice
la creazione di siti accessibili (perchè il codice HTML non
viene sporcato da elementi presentazionali estranei), ha un
ottimo livello di supporto da parte dei browser.
La versione più recente di CSS è la 3 (CSS3) e, al contrario
delle versioni precedenti, è suddivisa in moduli, ciascuno
dei quali dedicato ad una specifica funzionalità. Alcuni
moduli hanno raggiunto un buon livello di
standardizzazione mentre altri sono ancora sperimentali.
Come per HTML5, il livello di compatibilità dei browser
con CSS3 è variabile ed è quindi necessario fare attenzione
alle funzionalità che si utilizzano, cercando di evitare quelle
che non consentono di mantenere compatibilità all'indietro
con le versioni precedenti di CSS, in particolare CSS2.1.
Regole di stile
La sintassi utilizzata da CSS è diversa da quella HTML. Un
foglio di stile CSS è costituito da una o più regole di stile
che descrivono come dovrebbero essere visualizzati un
elemento o un gruppo di elementi HTML. Ogni regola
seleziona un elemento e dichiara come questo deve essere
presentato. Il seguente frammento di codice CSS mostra
due regole di stile: la prima definisce il colore del testo per
l'elemento <h1>; la seconda definisce dimensione e tipo di
font utilizzati per l'elemento <p>.
h1 {
color: green;
}
p {
font-size: small;
font-family: sans-serif;
}
Nella terminologia CSS, i due componenti principali di una
regola sono il selettore, che definisce a cosa si applica la
regola, e la dichiarazione, che specifica le istruzioni da
applicare. Una dichiarazione è a sua volta suddivisa in una
proprietà (ad esempio “color” nella prima regola
dell'esempio sopra) ed un valore (“green” nella prima
regola dell'esempio sopra), separati da due punti ed uno
spazio. I possibili valori dipendono dalla specifica proprietà
considerata. Ci possono essere una o più dichiarazioni per
ogni regola ed il blocco di dichiarazioni viene racchiuso da
parentesi graffe. Ogni dichiarazione deve essere separata
dalla successiva tramite un punto e virgola (l'ultimo è
opzionale ma è preferibile inserirlo). Nell'esempio
precedente, il selettore specifica il nome di un elemento e la
relativa regola viene applicata a tutte le istanze di
quell'elemento all'interno del documento a cui viene
associato il foglio di stile. Come vedremo in seguito, CSS
supporta anche selettori più sofisticati.
Applicazione dello stile
Ci sono tre modi per applicare informazione di stile ad un
documento HTML:
• Fogli di stile esterni. Le regole di stile vengono
incluse in un file di testo con estensione .css e
importate nel documento HTML tramite l'elemento
vuoto <link> oppure la regola @import. Il metodo più
comune è l'utilizzo dell'elemento <link> all'interno
dell'elemento <head>. In tal caso, è necessario
specificare i due attributi “rel” (tipo di documento a cui
si sta facendo riferimento; assume valore stylesheet per
i fogli di stile) e “href” (path del documento), come
nell'esempio seguente.
<!DOCTYPE html>
<html>
<head>
<title>Tecnologie web</title>
<link rel="stylesheet" href="css/stile.css" />
</head>
<body>
<p>A questo paragrafo vengono applicate <em>regole
distile</em> in cascata.</p>
</body>
</html>
Prima di HTML5 era anche necessario inserire
l'attributo “type” con valore text/css. E' possibile
inserire più elementi link per fare riferimento a più
fogli di stile per lo stesso documento.
Il secondo metodo per applicare un foglio di stile
esterno è utilizzare la regola @import all'inizio di un
elemento <style> (questo elemento viene utilizzato per
definire fogli di stile embedded come spiegato nel
punto seguente; in tal caso le regole di stile devono
essere inserite successivamente alla regola @import).
La regola @import definisce il path a cui trovare il
foglio di stile esterno.
<!DOCTYPE html>
<html>
<head>
<title>Tecnologie web</title>
<style>
@import url("css/stile.css");
</style>
</head>
<body>
<p>A questo paragrafo vengono applicate <em>regole di
stile</em> in cascata.</p>
</body>
</html>
Come per il metodo basato su <link> si possono
importare più fogli di stile anche tramite @import. La
regola @import può anche essere utilizzata all'interno
di un foglio di stile esterno.
Il vantaggio di utilizzare fogli di stile esterni è che è
possibile applicare lo stesso foglio di stile a più
documenti HTML.
• Fogli di stile embedded. Le regole di stile vengono
incluse nel documento HTML tramite utilizzo
dell'elemento <style>, inserito comunemente all'interno
di <head> (HTML5 consente di includerlo all'interno
di <body>). E' possibile utilizzare l'attributo “type” per
specificare il tipo di foglio di stile (non necessario in
HTML5). Le regole specificate in questo modo si
applicano solamente al documento in cui sono incluse.
Il seguente esempio di foglio di stile embedded mostra
anche la sintassi da utilizzare per inserire commenti
all'interno di un foglio di stile.
<!DOCTYPE html>
<html>
<head>
<title>Tecnologie web</title>
<style type="text/css">
/* Qui vengono inserite le regole */
p {
color: red;
font-family: sans-serif;
}
</style>
</head>
<body>
<p>A questo paragrafo vengono applicate regole di
stile definite in modo embedded.</p>
</body>
</html>
• Regole di stile inline. E' possibile applicare regole di
stile a singoli elementi all'interno di un documento
HTML mediante l'utilizzo dell'attributo “style”. Più
regole possono essere incluse separate tramite punto e
virgola.
<p style="color: red; font-family: sans-serif;"> A
questo paragrafo vengono applicate regole di stile definite in
modo inline.</p>
Questo tipo di soluzione dovrebbe essere evitata a
meno che non sia assolutamente necessario per
sovrascrivere una regola importata tramite i metodi
precedenti.
Concetti fondamentali
Ereditarietà
Un primo concetto fondamentale relativo a CSS è che gli
elementi HTML ereditano alcune regole di stile degli
elementi nei quali sono contenuti.
<!DOCTYPE html>
<html>
<head>
<title>Tecnologie web</title>
<style type="text/css">
p {
color: red;
font-family: sans-serif;
}
</style>
</head>
<body>
<p>A questo paragrafo vengono applicate <em>regole di
stile</em> definite in modo embedded.</p>
</body>
</html>
Nell'esempio precedente, all'elemento <em> viene applicato
lo stesso stile dell'elemento <p> nel quale è contenuto (oltre
allo specifico stile di default). Se l'elemento <p> fosse
contenuto all'interno di un altro elemento a cui viene
applicato uno stile relativo al testo, quello stile verrebbe
ereditato sia da <p> che da <em>, e così via. Per poter
capire quali regole di stile vengono applicate ad un
elemento è quindi fondamentale tenere in considerazione la
gerarchia degli elementi all'interno del documento html.
Bisogna comunque considerare che non tutte le proprietà
sono supportate da tutti gli elementi. Ad esempio, un
elemento <img> inserito all'interno del paragrafo
dell'esempio precedente non erediterebbe le regole del
paragrafo in quanto quelle specifiche regole (relative al
font) non si applicano alle immagini. Inoltre, ci sono
proprietà che normalmente non vengono ereditate come, ad
esempio, quelle relative a margini, bordi, o background.
L'ereditarietà può essere sfruttata per semplificare i fogli di
stile. Ad esempio, se si vuole applicare un certo font a tutti
gli elementi testuali di un documento, non serve aggiungere
una regola per ogni elemento ma basta inserire la regola per
l'elemento <body> in modo tale che venga ereditata da tutti
gli elementi testuali racchiusi in <body>.
Una regola ereditata può essere ridefinita in uno specifico
elemento in modo da applicare uno stile diverso a
quell'elemento, come nell'esempio seguente.
<!DOCTYPE html>
<html>
<head>
<title>Tecnologie web</title>
<style type="text/css">
p {
color: red;
font-family: sans-serif;
}
em {
color: blue;
}
</style>
</head>
<body>
<p>A questo paragrafo vengono applicate <em>regole di
stile</em> definite in modo embedded.</p>
</body>
</html>
Conflitti di stile
Quando si applica informazione di stile ad un documento,
possono presentarsi conflitti tra le regole. Questo può
accadere perchè CSS consente di applicare più fogli di stile
allo stesso documento o perchè sono state definite regole
conflittuali all'interno di uno stesso foglio di stile.
I conflitti tra fogli di stile possono essere risolti grazie al
fatto che esiste una gerarchia delle diverse sorgenti di
informazione di stile. In particolare, le regole definite ad un
livello della gerarchia vengono passate anche ai livelli
seguenti (da cui il termine “cascading” in CSS). Se viene
incontrata ad un livello una regola già definita ad un livello
precedente, la regola precedente viene sostituita da quella
corrente (in pratica, più si scende nella gerarchia più il peso
delle regole aumenta). Il risultato è un foglio di stile che
combina (con eventuali ridefinizioni in caso di conflitto) le
regole incluse nei diversi fogli di stile applicati ad un
documento. La gerarchia considerata da CSS è la seguente:
• Foglio di stile di default del browser
• Foglio di stile dell'utente (tutti i browser permettono di
creare un CSS che sostituisce il foglio di stile di
default)
• Foglio di stile esterno aggiunto tramite elemento
<link>
• Foglio di stile esterno importato tramite regola
@import
• Foglio di stile embedded tramite elemento <style>
• Informazione di stile inline (attributo “style”)
• Regole di stile marcate dall'autore con l'indicatore
!important
• Regole di stile marcate dall'utente con l'indicatore
!important
Nell'esempio seguente vengono applicate in cascata delle
regole embedded e delle regole inline. Come si vede, le
regole inline hanno la precedenza su quelle embedded.
<!DOCTYPE html>
<html>
<head>
<title>Tecnologie web</title>
<style type="text/css">
p {
color: red;
font-family: sans-serif;
}
</style>
</head>
<body>
<p style="color: black">A questo paragrafo vengono
applicate regole di stile in cascata.</p>
</body>
</html>
Nell'esempio seguente viene utilizzato l'indicatore
!important per dare peso maggiore alla regola embedded
relativa alla proprietà “color”.
<!DOCTYPE html>
<html>
<head>
<title>Tecnologie web</title>
<style type="text/css">
p {
color: red !important;
font-family: sans-serif;
}
</style>
</head>
<body>
<p style="color: black">A questo paragrafo vengono
applicate regole di stile in cascata.</p>
</body>
</html>
Nel caso in cui ci siano più fogli di stile esterni (quindi allo
stesso livello) che entrano in conflitto tra loro, vince il
foglio che viene inserito per ultimo nel codice.
Oltre ai conflitti dovuti alla presenza di sorgenti di stile
diverse, ci possono essere conflitti anche all'interno di uno
stesso foglio di stile. Questi possono essere dovuti alla
presenza di selettori diversi per lo stesso elemento, più
versioni dello stesso selettore con regole differenti per la
stessa proprietà, regole differenti per la stessa proprietà
all'interno dello stesso selettore. Nel primo caso, vince il
selettore più specifico (finora abbiamo visto un solo tipo di
selettore, quello più generico che indica il nome di un
elemento). Nel secondo e terzo caso, vince la regola che
appare per ultima. Nei due frammenti di codice seguenti, ad
esempio, la regola vincente è quella che assegna il colore
green alla proprietà “color”.
<style>
p { color: red; }
p { color: blue; }
p { color: green; }
</style>
<style>
p {
color: red;
color: blue;
color: green;
}
</style>
Box model
Un altro concetto generale di CSS, alla base del sistema di
formattazione visuale del contenuto, è il cosiddetto box
model. Ogni browser vede ogni elemento html di una
pagina (sia esso di tipo blocco che di tipo inline) come
racchiuso all'interno di un box rettangolare. Tramite CSS è
possibile definire proprietà di questi box come i bordi, i
margini, il background ed altre, oltre a poterne definire il
posizionamento sulla pagina web. L'esempio seguente
evidenzia i diversi box tramite utilizzo della proprietà
“border” dei diversi elementi. Notate come i box relativi
agli elementi blocco occupino la pagina per tutta la sua
larghezza mentre i box per gli elementi inline racchiudono
solo il contenuto dell'elemento.
<!DOCTYPE html>
<html>
<head>
<title>
Tecnologie web
</title>
<style type="text/css">
h1, h2, p, em, img { border: 1px solid blue; }
</style>
</head>
<body>
<article>
<h1>Documentazione su Java</h1>
<section>
<h2>Introduzione al linguaggio</h2>
<p>Uno dei principi fondamentali del linguaggio
Java è espresso dal motto <em>write once, run
anywhere</em> ...</p>
<figure><img src="../imgs/java.jpg"
alt=""/></figure>
</section>
<section>
<h2>Storia</h2>
<p>Java è stato creato a partire da ricerche
effettuate alla Stanford University agli inizi degli anni
Novanta ...</p>
</section>
</article>
</body>
</html>
L'esempio precedente evidenzia anche un modo compatto
per definire le stesse regole per elementi diversi: è
sufficiente raggruppare i selettori, separati da virgole, e
definire un solo blocco di dichiarazioni.
Tipi principali di selettore
In tutti gli esempi precedenti, abbiamo utilizzato il nome
degli elementi html come selettori. Lo svantaggio di
selezionare elementi in questo modo è che le regole
specificate vengono applicate a tutti gli elementi di quel
tipo nella pagina. Se vogliamo applicare regole in modo più
specifico, dobbiamo utilizzare altri tipi di selettore.
Selettori di discendenti
Un selettore di discendente specifica elementi che sono
contenuti in (e quindi sono discendenti di) altri elementi.
Per definire un selettore di discendente si indica l'elemento
contenitore seguito dall'elemento discendente, separati da
uno spazio. Nell'esempio seguente, specifichiamo un
selettore di discendente per gli elementi <em> contenuti
all'interno di elementi <p>. Notate che abbiamo anche
specificato un selettore generico per l'elemento <em> ma
che la regola che viene applicata è quella del selettore più
specifico.
<!DOCTYPE html>
<html>
<head>
<title>
Tecnologie web
</title>
<style type="text/css">
em { color: red; }
p em { color: blue; }
</style>
</head>
<body>
<article>
<h1>Documentazione su <em>Java</em></h1>
<section>
<h2>Introduzione al linguaggio</h2>
<p>Uno dei principi fondamentali del linguaggio
Java è espresso dal motto <em>write once, run
anywhere</em> ...</p>
<figure><img src="../imgs/java.jpg"
alt=""/></figure>
</section>
</article>
</body>
</html>
E' anche possibile avere livelli di innestamento multipli. La
regola seguente, ad esempio, si applica agli elementi <em>
contenuti all'interno di elementi <a> contenuti in liste non
ordinate <ol>.
ol a em { color: gray; }
Selettori di figli
Nella definizione di selettori di discendenti vista in
precedenza, non è impostante che l'elemento contenitore sia
il padre dell'elemento di cui vogliamo specificare le regole
di stile, è sufficiente che sia un suo antenato. Se vogliamo
invece specificare regole che valgono per i figli diretti di
uno specifico elemento, dobbiamo utilizzare i selettori di
figli che vengono specificati separando padre e figlio con
un simbolo di maggiore, come nell'esempio seguente.
p > em { color: yellow; }
La regola sopra definita si applicherà agli elementi <em>
che sono direttamente contenuti all'interno di elementi <p>
ma non ad elementi <em> contenuti all'interno di altri
elementi anche se questi ultimi sono contenuti all'interno di
elementi <p>.
Selettori di fratelli adiacenti
Un selettore di fratelli adiacenti identifica un elemento che
appare nel codice immediatamente dopo un altro elemento
all'interno dello stesso padre. I due elementi vengono
separati dal simbolo +. La regola seguente si applica ad
esempio a paragrafi <p> che seguono immediatamente un
elemento <h1>.
h1 + p
{ color: red; }
Selettori di fratelli generici
Un selettore di fratello generico identifica un elemento che
appare successivamente ad un altro elemento all'interno
dello stesso padre . Questo tipo di selettore è stato introdotto
in CSS3. L'esempio seguente si applica ad elementi <h2>
che appaiono dopo elementi <h1> (ma non necessariamente
subito dopo) all'interno dello stesso padre.
h1 ~ h2 { color: red; }
Selettori di id
Abbiamo visto in precedenza come l'attributo “id” possa
essere utilizzato per assegnare un identificatore univoco ad
un qualsiasi elemento html. Un selettore di id consente di
creare regole di stile per un elemento identificato da uno
specifico id. Per creare un tale selettore, è sufficiente unire
il nome dell'elemento al valore dell'attributo “id” tramite
l'utilizzo del simbolo #. Nell'esempio seguente viene creata
una regola di stile per un elemento <p> con id par12.
p#par12 { color: red; }
Dato che gli dovrebbero essere unici, è anche possibile
tralasciare il nome dell'elemento scrivendo solo il valore
dell'id preceduto dal simbolo #.
Un selettore di id può essere utilizzato anche come parte di
un selettore contestuale (uno qualsiasi dei selettori visti
nelle precedenti 4 sezioni). Il frammento seguente, ad
esempio, definisce una regola per tutti gli elementi <em>
contenuti all'interno del paragrafo con id par12.
#par12 em { color: red; }
Selettori di classe
Oltre ad identificare un elemento tramite “id”, abbiamo
visto in precedenza che l'attributo “class” può essere
utilizzato per classificare un certo elemento come
appartenente ad un gruppo. A differenza di “id”, più
elementi possono appartenere allo stesso gruppo ed un
elemento può appartenere a più gruppi. Un selettore di
classe permette di specificare regole di stile per gli elementi
appartenenti ad una specifica classe. In modo simile ai
selettori di id, è possibile creare un selettore di classe
unendo il nome dell'elemento al valore dell'attributo “class”
tramite l'utilizzo di un punto. Nell'esempio seguente viene
creata una regola di stile per tutti gli elementi <p> con
attributo “class” di valore intro.
p.intro { color: red; }
Se vogliamo applicare una regola a tutti gli elementi di una
certa classe (indipendentemente dal loro tipo), è sufficiente
indicare solo il nome della classe preceduta dal punto, come
nell'esempio seguente.
.intro { color: red; }
Conflitti di stile tra selettori
Abbiamo visto in precedenza come risolvere conflitti di
stile nel caso di sorgenti di stile diverse o nel caso di più
versioni dello stesso selettore. Nel caso di conflitti tra
selettori diversi all'interno dello stesso foglio di stile
esistono delle regole di precedenza (in realtà abbastanza
complicate, si veda
http://www.w3.org/TR/CSS21/cascade#specificity) che
possono essere riassunte in modo semplificato come segue:
• I selettori di id sono più specifici e sovrascrivono
• i selettori di classe, che sono più specifici e
sovrascrivono
• i selettori contestuali, che sono più specifici e
sovrascrivono
• i selettori di elemento.
Quindi, nel seguente esempio, il selettore contestuale di
discendente ha la precedenza sul selettore di elemento ed il
testo dell'elemento <em> all'interno dei paragrafi comparirà
in colore verde.
em { color: red; }
p em { color: green; }
Nell'esempio seguente, gli elementi <em> di classe nero
verranno visualizzati con colore nero anche quando
compaiono all'interno di paragrafi, poiché i selettori di
classe hanno la precedenza sugli altri due selettori
specificati.
em { color: red; }
p em { color: green; }
em.nero { color: black; }
Altri selettori
Oltre a quelli descritti in precedenza, esistono altri tipi di
selettore che vengono utilizzati in casi particolari. Nelle
sezioni seguenti, vedremo i più comuni mentre all'indirizzo
http://www.w3.org/TR/2011/REC-css3-selectors-20110929/
potete trovare l'elenco completo.
Selettori di pseudo-classe
Durante la navigazione dei siti web, il browser tiene traccia
di alcuni stati nei quali si possono trovare gli elementi. Ad
esempio, viene tenuta traccia del fatto che un link sia stato
cliccato oppure no. Tutti gli elementi che si trovano nello
stesso stato fanno parte della stessa classe ma tali classi non
sono definite esplicitamente nel codice, da cui il nome
pseudo-classi. E' comunque possibile andare a modificare
lo stile degli elementi che si trovano in una particolare
pseudo-classe attraverso un tipo di particolare di selettore
che dipende dal nome dello stato che si sta considerando.
I selettori di pseudo-classe più utilizzati sono quelli relativi
ai link (elementi <a>). In particolare, è possibile
identificare tutti i link che non sono ancora stati cliccati e
tutti i link che sono già stati visitati. Ciò può avvenire
utilizzando i selettori :link e :visited come nell'esempio
seguente.
a:link { color: maroon; }
a:visited { color: gray; }
Inoltre, si possono utilizzare i selettori :focus, :hover e
:active per indicare rispettivamente elementi (non solo link)
che sono in uno stato selezionato (hanno il focus come ad
esempio un campo di testo su cui l'utente sta scrivendo), su
cui è posizionato il puntatore del mouse, o che sono in
procinto di essere attivati.
a:hover { color: gray; }
a:active { color: red; }
Quando vengono applicati degli stili ai link utilizzando
questi selettori, il loro ordine nei fogli di stile è importante
e DEVE essere :link, :visited, :focus, :hover, :active.
CSS3 definisce diversi altri selettori di pseudo-classe, la
maggior parte dei quali consentono la selezione di elementi
in base a dove tali elementi sono posizionati all'interno
della struttura di un documento. Un elenco completo con
esempi è disponibile al seguente link:
http://www.w3.org/TR/2011/REC-css3-selectors20110929/#pseudo-classes.
Tenete anche presente che è possibile combinare tra loro le
diverse categorie di selettori per ottenere risultati come
applicare uno stile ai link visitati di una particolare classe.
a.mainmenu:visited { color: gray; }
Selettori di attributo
I selettori di attributo permettono di selezionare degli
elementi in base ai loro attributi. E' possibile sia effettuare
selezioni in base al nome degli attributi che in base al
valore degli attributi.
Il selettore di attributo semplice permette di selezionare
elementi in base al nome di un attributo. Ad esempio, la
regola seguente si applica agli elementi <img> che hanno
definito l'attributo “title”.
img[title] {border: 3px solid;}
Il selettore di attributo con valore esatto seleziona elementi
in base ad uno specifico valore di un attributo. Ad esempio,
la regola seguente si applica agli elementi <img> che hanno
definito l'attributo “title” con valore Logo (la selezione è
case-sensitive).
img[title=“Logo”] {border: 3px solid;}
Ci sono diversi altri selettori di attributo più specifici per
situazioni in cui si vuole ad esempio selezionare elementi in
base a parte del valore di un attributo. Si veda
http://www.w3.org/TR/2011/REC-css3-selectors20110929/#attribute-selectors per un elenco completo.
Selettore universale
Il selettore universale, identificato dal simbolo di asterisco
(*) permette di selezionare qualsiasi elemento nel contesto
specificato. Ad esempio, la regola seguente rende di colore
grigio tutti gli elementi in foreground di un documento.
* { color: gray; }