Queste sono le note della lezione del corso su CSS. Nella lezione su HTML abbiamo costruito la pagina del menu di Awesome Pizza: ben strutturata, semantica, e onestamente bruttina. Oggi le diamo un aspetto.
CSS sta per Cascading Style Sheets ed è il linguaggio con cui si descrive la presentazione di una pagina: colori, spazi, dimensioni, disposizione degli elementi. Sul significato di quel “Cascading” torniamo a fine lezione, perché è la parte che spiega metà dei comportamenti strani che incontrerete.
Anche qui, per provare gli esempi vi suggerisco CodePen.
Come si collega il CSS
Ci sono tre modi per applicare del CSS a una pagina:
<!-- 1. Inline, direttamente sull'elemento -->
<p style="color: red;">La migliore pizza di Paperopoli.</p>
<!-- 2. In un blocco style dentro head -->
<style>
p {
color: red;
}
</style>
<!-- 3. In un file esterno, collegato nell'head -->
<link rel="stylesheet" href="style.css" />
Noi useremo sempre il file esterno: lo stile sta in un posto solo, vale per tutte le pagine del sito e il browser lo tiene in cache. Lo stile inline è da evitare, perché sparpaglia la presentazione dentro la struttura ed è il più difficile da sovrascrivere dopo.
Selettori
Una regola CSS è fatta da un selettore, che dice a quali elementi si applica, e da un blocco di dichiarazioni:
/* Tutti i paragrafi */
p {
color: #333333;
}
/* Tutti gli elementi con class="card" */
.card {
background-color: white;
}
/* L'elemento con id="menu" */
#menu {
margin-top: 32px;
}
/* I paragrafi dentro le card */
.card p {
font-size: 14px;
}
Il selettore che userete più di tutti è la classe. Il tag va bene per gli stili di base del sito, l’id identifica un elemento unico nella pagina, e i selettori si possono combinare per scendere nel dettaglio, come nell’ultimo esempio.
Quando due regole vogliono impostare la stessa proprietà sullo stesso elemento, vince la più specifica: un id pesa più di una classe, una classe pesa più di un tag. A parità di specificità vince la regola letta per ultima.
DON’T: !important
Esiste un modo per vincere sempre: aggiungere !important alla dichiarazione. Funziona, ed è proprio questo il problema. La prossima persona che dovrà modificare quello stile potrà vincere solo con un altro !important, e da lì in poi lo stylesheet diventa una gara al rialzo dove non vince più nessuno. Se sentite il bisogno di !important, nove volte su dieci il problema vero è un selettore troppo specifico da qualche altra parte.
Per lo stesso motivo vi consiglio di non usare gli id per lo styling: hanno una specificità altissima e si sovrascrivono male. Teneteli per le ancore e per JavaScript, e date una classe all’elemento.
Unità di misura
Le tre unità che ci servono subito:
px, un valore assoluto. Va benissimo per bordi e dettagli.%, relativa all’elemento genitore. Utile per le larghezze.rem, relativa alla dimensione del font della radice del documento, che di default è 16px. Quindi1rem= 16px,1.5rem= 24px.
Il motivo per preferire rem per i testi è l’accessibilità: se l’utente alza la dimensione del font nelle impostazioni del browser, i testi in rem si adattano, quelli in px restano dove sono.
Il box model
Per il CSS ogni elemento è una scatola fatta di quattro strati: il contenuto, il padding (lo spazio tra contenuto e bordo), il border e il margin (lo spazio fuori dal bordo, verso gli altri elementi).
Diamo una forma alla card di una pizza:
.card {
width: 300px;
padding: 16px;
border: 1px solid #dddddd;
margin: 8px;
}
Domanda da lezione: quanto è larga questa card? La risposta storica del CSS è 334px, perché width indica solo il contenuto, e padding e bordo si sommano fuori: 300 + 16×2 + 1×2. È un comportamento che genera conti strani e layout che sbordano, e infatti praticamente ogni progetto inizia con questa regola:
* {
box-sizing: border-box;
}
Con border-box, width indica la larghezza tutto compreso: la card è larga 300px, punto, e il contenuto si restringe per fare spazio a padding e bordo. Questa è la riga che avete visto copiata mille volte: ora sapete cosa fa.
Display
Ogni elemento ha un comportamento di base nel layout, controllato dalla proprietà display:
block: occupa tutta la riga e accetta dimensioni. Sono block idiv, i paragrafi, gli heading.inline: scorre nel testo e ignorawidtheheight. Sono inline i link,strong,em.inline-block: scorre nel testo ma accetta dimensioni.
Sono i comportamenti di default, e si possono cambiare. Il cambio di display più interessante è il prossimo.
Flexbox
Vogliamo le card delle pizze una accanto all’altra, ben distanziate, che vadano a capo se non ci stanno. Prima ricostruiamo il menu con le card:
<section class="menu">
<article class="card">
<h3>Margherita</h3>
<p>Pomodoro, mozzarella, basilico</p>
<p class="prezzo">9€</p>
</article>
<!-- le altre card -->
</section>
Poi attiviamo flexbox sul contenitore:
.menu {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 16px;
}
I concetti da portare a casa:
- Flexbox si attiva sul contenitore (
display: flex) e dispone i figli diretti. justify-contentdistribuisce gli elementi lungo l’asse principale (di default orizzontale),align-itemsli allinea sull’asse perpendicolare.gapmette spazio tra gli elementi, senza i giochi di margini che si facevano una volta.flex-wrap: wrapmanda a capo gli elementi che non ci stanno.
Prima di flexbox queste disposizioni si ottenevano con float e molta pazienza. Se in un progetto datato trovate dei float usati per il layout, ora sapete da quale epoca arrivano.
Pseudo-classi
Le pseudo-classi selezionano un elemento in un particolare stato. La più usata è :hover, lo stato in cui il puntatore è sopra l’elemento:
.card:hover {
border-color: #e63312;
}
button:hover {
background-color: #c42a0e;
}
Una sorella meno famosa ma più importante è :focus, lo stato dell’elemento selezionato con la tastiera: chi naviga con il tab deve poter capire dove si trova, quindi non rimuovete mai l’outline di focus senza fornire un’alternativa visibile.
La cascata e l’ereditarietà
Eccoci alla C di CSS. Gli stili di una pagina arrivano da più fonti: il foglio di stile di default del browser (è lui il responsabile del Times New Roman), i nostri file, gli eventuali stili inline. La cascata è l’algoritmo che decide, per ogni proprietà di ogni elemento, quale dichiarazione vince: conta l’origine, poi la specificità del selettore, poi l’ordine.
L’ereditarietà è il secondo meccanismo: alcune proprietà, come color e font-family, scendono dagli elementi ai loro discendenti. Per questo il font di tutto il sito si imposta una volta sola:
body {
font-family: "Helvetica Neue", Arial, sans-serif;
color: #333333;
}
Le proprietà del box model invece non si ereditano, e per fortuna: un margine che si propaga a tutti i discendenti sarebbe un incubo.
Quando uno stile non si applica come vi aspettate, il posto dove guardare sono i DevTools del browser: tasto destro, Ispeziona, e il pannello degli stili vi mostra tutte le regole in conflitto, con quelle perdenti sbarrate. È il singolo strumento che vi farà capire il CSS più di qualsiasi lezione.
Media query
Metà dei vostri utenti ordina la pizza dal telefono, quindi il layout deve funzionare anche lì. Le media query applicano regole solo quando una condizione è vera:
@media (max-width: 600px) {
.menu {
flex-direction: column;
align-items: stretch;
}
}
Sotto i 600px di larghezza le card si dispongono in colonna, una sotto l’altra. Del responsive design ci sarebbe da fare una lezione intera; per ora vi basta il meccanismo.
Lo stylesheet della pizzeria per ora è piccolo e si lascia gestire. Nella prossima lezione vedremo cosa succede quando cresce, e quali strumenti esistono per tenerlo in ordine.
Per approfondire
- CSS su MDN
- Flexbox Froggy - per imparare flexbox giocando
- CSS Diner - per imparare i selettori giocando