Manuale completo di CSS
Dalla prima regola di stile al layout responsive: guida a 3 livelli con centinaia di esempi spiegati nel dettaglio, demo live, 60 esercizi e un progetto finale.
0Cos'è CSS Base
Immagina di costruire una casa. L'HTML sono i mattoni, le travi, i muri: definisce la struttura. Il CSS è tutto il resto: la vernice, il colore delle piastrelle, la posizione dei mobili. Senza CSS, il web sarebbe una noiosa sequenza di testo nero su sfondo bianco.
CSS (Cascading Style Sheets) è il linguaggio che descrive come apparire gli elementi HTML. Il termine "a cascata" si riferisce al modo in cui le regole vengono applicate: se più regole si applicano allo stesso elemento, il browser decide quale usare seguendo un ordine preciso.
Anatomia di una regola
Ogni regola CSS è composta da un selettore e un blocco di dichiarazioni:
h1 { color: #142850; /* dichiarazione */ font-size: 2rem; }
- Selettore (
h1): dice al browser quale elemento deve essere stilizzato. - Dichiarazione (
color: #142850): è composta da una proprietà (color) e un valore (#142850). - Regola: è l'insieme di selettore + blocco
{ }.
HTML = struttura · CSS = presentazione · JavaScript = comportamento. Tenerli separati rende il codice più pulito e manutenibile.
1Sintassi e collegamento Base
Ci sono tre modi per collegare il CSS a una pagina HTML. Solo uno è quello giusto per un progetto serio.
1.1 CSS inline (sconsigliato)
Scrivi lo stile direttamente nell'HTML. Funziona, ma è un incubo da gestire se devi cambiare qualcosa. Immagina di avere 100 paragrafi e voler cambiare il colore: dovresti modificarli tutti a mano.
<p style="color: red; font-size: 20px;">Ciao</p>
1.2 CSS interno
Scrivi il codice in un tag <style> dentro l'<head>. Va bene per pagine singole o prototipi.
<head> <style> h1 { color: #2E6FF2; } </style> </head>
1.3 CSS esterno (consigliato)
Il CSS vive in un file separato (es. style.css) che viene collegato con il tag <link>. Questo è il metodo standard: puoi riutilizzare lo stesso foglio di stile su mille pagine diverse. Se cambi il colore in style.css, tutte le pagine collegate si aggiornano automaticamente.
<link rel="stylesheet" href="style.css">
Usa sempre il CSS esterno. Inline solo per test rapidi, interno solo per pagine singole. Su progetti veri, il CSS esterno è l'unica scelta sensata.
2Selettori Base
I selettori sono lo strumento più importante del CSS: dicono al browser quali elementi devono essere stilizzati. Senza selettori, non puoi applicare alcuna proprietà. È il primo argomento da padroneggiare dopo la sintassi.
2.1 Selettore universale *
Seleziona tutti gli elementi della pagina. Si usa quasi sempre per il reset iniziale (margin, padding, box-sizing).
* { margin: 0; padding: 0; box-sizing: border-box; }
Il selettore universale applica lo stile a ogni elemento, incluse le pseudo-classi ::before e ::after. Su pagine enormi può rallentare. Per il reset va benissimo, ma non abusarne.
2.2 Selettore di tipo (o di tag)
Seleziona tutti gli elementi di un certo tipo. Es: p seleziona tutti i <p>.
p { color: gray; } h1, h2, h3 { font-family: 'Sora', sans-serif; }
Con la virgola puoi applicare la stessa regola a più selettori: h1, h2, h3 { ... }. Riduce la duplicazione del codice.
2.3 Selettore di classe .nome
Seleziona tutti gli elementi con un certo attributo class. È il selettore più usato in assoluto, perché è riutilizzabile.
<p class="intro">Benvenuto</p> <p class="intro evidenziato">Importante</p> <p>Testo normale</p>
.intro { color: #2E6FF2; font-weight: 600; } .evidenziato { background: #FEF2E0; }
Benvenuto (classe .intro)
Importante (classi .intro .evidenziato)
Testo normale (nessuna classe)
2.4 Selettore di ID #nome
Seleziona l'elemento con un certo attributo id. L'ID deve essere unico nella pagina. Ha specificità più alta della classe.
<div id="main">Contenuto principale</div>
#main { max-width: 1080px; margin: 0 auto; }
Gli ID si usano per identificare un unico elemento (es. per JavaScript o ancore). Le classi si usano per lo stile, perché sono riutilizzabili. Regola pratica: non usare mai ID per lo stile, solo classi.
2.5 Selettore di attributo [attr]
Seleziona elementi in base alla presenza o al valore di un attributo. Utilissimo per stilizzare link, input, immagini.
| Selettore | Seleziona | Esempio |
|---|---|---|
[href] | Elementi con attributo href | a[href] { color: blue; } |
[type="email"] | Attributo esattamente uguale | input[type="email"] { border: 2px solid blue; } |
[href^="https"] | Inizia con "https" | a[href^="https"] { color: green; } |
[href$=".pdf"] | Finisce con ".pdf" | a[href$=".pdf"]::after { content: " 📄"; } |
[href*="lezia"] | Contiene "lezia" | a[href*="lezia"] { font-weight: bold; } |
[class~="box"] | Contiene la parola "box" | [class~="box"] { padding: 1rem; } |
[lang|="it"] | Inizia con "it-" o è "it" | [lang|="it"] { font-style: italic; } |
2.6 Combinatori: relazioni tra elementi
I combinatori selezionano elementi in base alla loro posizione nell'albero HTML.
| Combinatore | Sintassi | Seleziona | Esempio |
|---|---|---|---|
| Discendente | A B | Tutti i B dentro A (anche annidati) | div p |
| Figlio diretto | A > B | Solo i B figli diretti di A | ul > li |
| Fratello adiacente | A + B | Il primo B subito dopo A | h2 + p |
| Fratelli generali | A ~ B | Tutti i B dopo A (stesso genitore) | h2 ~ p |
<ul class="menu">
<li>Voce 1</li>
<li><a href="#">Voce 2</a></li>
</ul>
ul > li seleziona solo i <li> figli diretti.
ul a (discendente) seleziona il link dentro il <li>.
2.7 Riepilogo dei selettori
| Tipo | Sintassi | Esempio |
|---|---|---|
| Universale | * | * { margin: 0; } |
| Tag | p | p { color: gray; } |
| Classe | .box | .box { padding: 1rem; } |
| ID | #main | #main { max-width: 1080px; } |
| Attributo | [type="email"] | input[type="email"] { border: 2px solid blue; } |
| Discendente | div p | div p { margin: 1rem 0; } |
| Figlio | div > p | div > p { font-weight: 700; } |
| Fratello adiacente | h2 + p | h2 + p { margin-top: 0; } |
| Fratelli generali | h2 ~ p | h2 ~ p { color: gray; } |
3Colori Base
Il colore è l'elemento più visibile. In CSS puoi definirlo in diversi formati: nomi, esadecimali, RGB, HSL. Ognuno ha i suoi vantaggi.
3.1 Formati a confronto
| Formato | Esempio | Quando usarlo |
|---|---|---|
| Nome | red, teal, tomato | Prototipi veloci |
| Esadecimale | #2E6FF2, #fff | Standard, preciso |
| RGB / RGBA | rgb(46 111 242 / 50%) | Trasparenze |
| HSL / HSLA | hsl(220 88% 57%) | Palette programmatiche |
| oklch | oklch(60% 0.15 250) | Colori percettivi (moderno) |
3.2 opacity vs rgba: la differenza chiave
Questa è una delle distinzioni più importanti e confuse. opacity rende trasparente tutto l'elemento (incluso il testo e i bordi), mentre rgba agisce solo sul colore di sfondo.
solo lo sfondo è trasparente
tutto è trasparente
Un testo leggibile deve avere un rapporto di contrasto di almeno 4.5:1 rispetto allo sfondo. Testi grigi su sfondo bianco o viceversa sono spesso illeggibili. Verifica su WebAIM.
4Unità di misura Base
Quando scrivi font-size: 16px, stai usando un'unità di misura. Ma non tutte le unità sono uguali: alcune sono assolute (sempre uguali), altre relative (cambiano in base al contesto).
4.1 Unità assolute
Le unità assolute hanno sempre lo stesso valore, indipendentemente dal contesto. Si usano raramente perché non si adattano ai diversi dispositivi.
| Unità | Corrisponde a... | Quando usarla |
|---|---|---|
px | Pixel CSS (1/96 di pollice) | Bordi, ombre, dettagli fissi |
cm | Centimetri (1cm ≈ 37.8px) | Stampanti (raramente) |
mm | Millimetri (1mm ≈ 3.78px) | Stampanti (raramente) |
in | Pollici (1in = 96px = 2.54cm) | Stampanti (raramente) |
pt | Punti (1pt = 1/72 di pollice) | Stampanti (raramente) |
pc | Pica (1pc = 12pt) | Stampanti (raramente) |
4.2 Unità relative al font
| Unità | Relativa a... | Esempio | Quando usarla |
|---|---|---|---|
em | font-size dell'elemento (o del genitore) | 1.5em | Spaziature proporzionali al testo |
rem | font-size di <html> (di solito 16px) | 1.5rem = 24px | Font, spaziature (prevedibile) |
ch | Larghezza del carattere "0" | 65ch | Limitare righe di testo |
ex | Altezza della lettera "x" | 1ex | Raramente usato |
4.3 Unità relative al viewport
Il viewport è l'area visibile della finestra del browser. Queste unità si adattano alle dimensioni della finestra.
| Unità | Corrisponde a... | Esempio |
|---|---|---|
vw | 1% della larghezza viewport | 50vw |
vh | 1% dell'altezza viewport | 100vh |
vmin | 1% del lato più piccolo | 10vmin |
vmax | 1% del lato più grande | 10vmax |
dvh | Viewport dinamico (mobile) | 100dvh |
svh | Viewport piccolo | 100svh |
lvh | Viewport grande | 100lvh |
Su mobile, la barra degli indirizzi del browser può apparire/scomparire, cambiando l'altezza del viewport. vh non si adatta, causando problemi di layout. dvh (dynamic), svh (small) e lvh (large) risolvono questo problema.
4.4 Unità percentuali e frazionarie
| Unità | Relativa a... | Esempio |
|---|---|---|
% | Dimensione del genitore | width: 50% |
fr | Frazione dello spazio disponibile (solo Grid) | grid-template-columns: 1fr 2fr |
4.5 em vs rem: la differenza cruciale
Questa è una delle fonti di confusione principali. em è relativo alla dimensione del font del genitore, mentre rem è relativo alla dimensione del font della radice (<html>).
html { font-size: 16px; } .a { font-size: 20px; padding: 1em; } /* = 20px (relativo al genitore) */ .b { font-size: 20px; padding: 1rem; } /* = 16px (relativo alla radice) */
font-size:20px
Usa rem per font e spaziature (è prevedibile), px per bordi sottili, % e fr per layout, ch per limitare la lunghezza delle righe di testo, e dvh per altezze a schermo intero su mobile.
5Sfondi Base
Lo sfondo di un elemento può essere un colore solido, un'immagine, o un gradiente. CSS offre molte proprietà background-* per controllare ogni aspetto dello sfondo.
5.1 background-color
Imposta il colore di sfondo. Accetta qualsiasi formato colore.
.box { background-color: #2E6FF2; } .box-2 { background-color: rgb(46 111 242 / 50%); } .box-3 { background-color: transparent; } /* default */
5.2 background-image
Imposta un'immagine di sfondo. Può essere un URL, un gradiente, o più immagini sovrapposte.
.a { background-image: url('foto.jpg'); } .b { background-image: linear-gradient(135deg, #2E6FF2, #7C5CFC); } .c { background-image: linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url('foto.jpg'); /* overlay scuro sopra foto */ }
5.3 background-size: cover vs contain
Controlla come l'immagine si adatta al contenitore. Questa è la proprietà più confusa per i principianti.
| Valore | Effetto | Quando usarlo |
|---|---|---|
auto | Dimensione originale | Immagini piccole decorative |
cover | Copre tutto il contenitore (ritaglia) | Hero, sfondi a schermo intero |
contain | Mostra tutta l'immagine (lascia spazi) | Loghi, icone, immagini che non si possono tagliare |
100% 100% | Stira l'immagine | Raramente (distorce) |
200px 100px | Larghezza e altezza fisse | Pattern, texture |
5.4 background-repeat
Controlla se e come l'immagine si ripete.
| Valore | Effetto |
|---|---|
repeat | Ripete in entrambe le direzioni (default) |
no-repeat | Nessuna ripetizione |
repeat-x | Solo orizzontale |
repeat-y | Solo verticale |
space | Ripete con spazi uguali |
round | Ripete e scala per adattarsi |
5.5 background-position
Posiziona l'immagine di sfondo. Accetta parole chiave, percentuali o misure.
.a { background-position: center; } .b { background-position: top left; } .c { background-position: 50% 50%; } .d { background-position: 20px 40px; } .e { background-position: right 20px bottom 40px; }
5.6 background-attachment
Controlla se lo sfondo scorre con la pagina o rimane fisso.
| Valore | Effetto |
|---|---|
scroll | Scorre con la pagina (default) |
fixed | Rimane fisso mentre scorri (effetto parallasse) |
local | Scorre con il contenuto dell'elemento |
5.7 background-clip e background-origin
background-clip decide dove si applica lo sfondo (fino al bordo, al padding, al contenuto, o al testo). background-origin decide da dove parte il posizionamento.
.a { background-clip: border-box; } /* default: fino al bordo */ .b { background-clip: padding-box; } /* fino al padding */ .c { background-clip: content-box; } /* solo il contenuto */ .d { background: linear-gradient(90deg, #2E6FF2, #7C5CFC); -webkit-background-clip: text; background-clip: text; color: transparent; /* testo con gradiente */ }
5.8 background-blend-mode
Mescola più immagini di sfondo o un'immagine con un colore, usando le stesse modalità di Photoshop.
| Valore | Effetto |
|---|---|
normal | Nessun blending (default) |
multiply | Moltiplica (scurisce) |
screen | Schiarisce |
overlay | Contrasto |
darken | Più scuro dei due |
lighten | Più chiaro dei due |
color-dodge | Schiarisce i toni |
difference | Differenza assoluta |
5.9 background: shorthand
Tutte le proprietà precedenti possono essere scritte insieme con la scorciatoia background.
/* background: colore immagine posizione/size repeat attachment */ .d { background: #2E6FF2 url('foto.jpg') center / cover no-repeat fixed; }
Nello shorthand background, la position e la size vanno insieme separate da /. Se sbagli l'ordine, il browser ignora la regola.
5.10 Riepilogo proprietà sfondo
| Proprietà | Valori principali | Cosa fa |
|---|---|---|
background-color | Qualsiasi colore | Colore di sfondo |
background-image | url(), gradient() | Immagine o gradiente |
background-size | cover, contain, 100% | Dimensione immagine |
background-position | center, top left, 50% 50% | Posizione |
background-repeat | no-repeat, repeat-x, repeat-y | Ripetizione |
background-attachment | scroll, fixed, local | Scorrimento |
background-clip | border-box, padding-box, content-box, text | Area di applicazione |
background-origin | border-box, padding-box, content-box | Origine posizionamento |
background-blend-mode | multiply, screen, overlay, ... | Modalità fusione |
6Bordi e outline Base
Il bordo è una linea che circonda l'elemento. Puoi controllarne spessore, stile e colore. La proprietà border è una scorciatoia per border-width, border-style e border-color.
6.1 border-width
Lo spessore del bordo. Accetta misure (px, em, rem) o parole chiave (thin, medium, thick).
.a { border-width: 2px; } /* tutti i lati */ .b { border-width: 1px 2px; } /* vert | orizz */ .c { border-width: 1px 2px 3px 4px; } /* top right bottom left */ .d { border-top-width: 4px; } /* solo sopra */
6.2 border-style
Lo stile del bordo. Senza border-style, il bordo non appare nemmeno se hai impostato width e color.
| Valore | Effetto |
|---|---|
solid | Linea continua |
dashed | Tratteggiata |
dotted | Punteggiata |
double | Doppia linea |
groove | Effetto incavo 3D |
ridge | Effetto rilievo 3D |
inset | Effetto incassato |
outset | Effetto in rilievo |
none | Nessun bordo (default) |
hidden | Come none, ma in tabelle prevale |
6.3 border-color
.a { border-color: #2E6FF2; } .b { border-color: red blue green yellow; } /* top right bottom left */ .c { border-color: currentColor; } /* usa il colore del testo */
6.4 Shorthand: border
Le tre proprietà possono essere scritte insieme. L'ordine non conta, ma la convenzione è width style color.
.box { border: 2px solid #2E6FF2; } .misto { border-top: 2px solid red; border-right: 4px dashed blue; border-bottom: 1px dotted green; border-left: 3px double orange; }
6.5 border-radius: angoli arrotondati
Arrotonda gli angoli del bordo. Accetta uno, due, tre o quattro valori.
.a { border-radius: 8px; } /* tutti gli angoli */ .b { border-radius: 8px 16px; } /* top-left/bottom-right | top-right/bottom-left */ .c { border-radius: 8px 16px 24px; } /* top-left | top-right/bottom-left | bottom-right */ .d { border-radius: 8px 16px 24px 32px; } /* TL TR BR BL */ .pill { border-radius: 999px; } /* pillola */ .circle { border-radius: 50%; } /* cerchio (se quadrato) */ .ellisse { border-radius: 50% / 30%; } /* ellisse */
6.6 outline vs border
outline è una linea fuori dal bordo che non occupa spazio nel layout. È usata per il focus accessibile (quando navighi con il Tab).
| Proprietà | border | outline |
|---|---|---|
| Occupazione spazio | Sì | No |
| Angoli arrotondabili | Sì (border-radius) | No |
| Lati separati | Sì (top, right, bottom, left) | No (unica linea) |
| Uso tipico | Struttura visiva | Focus accessibile |
button:focus-visible { outline: 3px solid #2E6FF2; outline-offset: 2px; /* distanza dal bordo */ }
Chi naviga da tastiera usa il Tab. Se rimuovi l'outline, rendi impossibile capire dove si trovi il focus. Usa :focus-visible con uno stile alternativo se vuoi rimuoverlo.
7Margin e padding Base
Questa è una delle distinzioni più importanti. Immagina una scatola da spedizione: il padding è il pluriball all'interno, il margin è lo spazio che lasci tra una scatola e l'altra.
- Padding: spazio interno, tra il contenuto e il bordo.
- Margin: spazio esterno, tra l'elemento e gli altri elementi.
7.1 Padding
.a { padding: 20px; } /* tutti i lati */ .b { padding: 10px 20px; } /* vert | orizz */ .c { padding: 10px 20px 30px; } /* top | orizz | bottom */ .d { padding: 10px 20px 30px 40px; } /* top right bottom left */ .e { padding-top: 10px; } /* solo sopra */ .f { padding-inline: 20px; } /* proprietà logica: sinistra+destra */
7.2 Margin
.a { margin: 20px; } /* tutti i lati */ .b { margin: 0 auto; } /* centrato orizzontalmente */ .c { margin-top: -20px; } /* margine negativo */ .d { margin-inline: auto; } /* centrato (logico) */
7.3 Margin collapse: il comportamento che sorprende
Quando due margini verticali si incontrano, non si sommano ma si "sovrappongono". Vince il più grande. Questo è chiamato margin collapse.
P1 con margin-bottom: 30px
P2 con margin-top: 20px
Lo spazio tra i due è 30px, non 50px.
Un blocco con width fissa e margin: 0 auto si centra orizzontalmente. Non funziona con margin: auto su elementi senza larghezza definita.
Usa padding per distanziare il contenuto dal bordo (dentro la scatola). Usa margin per distanziare un elemento dagli altri (fuori dalla scatola).
8Proprietà del testo Base
Il testo è il contenuto principale di una pagina web. CSS offre decine di proprietà per controllarne l'aspetto.
8.1 color e text-align
p { color: #1B2733; } .center { text-align: center; } .justify { text-align: justify; }
8.2 text-decoration
| Valore | Effetto |
|---|---|
none | Nessuna decorazione |
underline | Sottolineato |
overline | Linea sopra |
line-through | Barrato |
underline dotted | Sottolineatura punteggiata |
Sottolineato
Linea sopra
Barrato
Sottolineato punteggiato
8.3 text-transform
testo in maiuscolo
TESTO IN MINUSCOLO
testo con iniziali maiuscole
8.4 text-indent, letter-spacing, word-spacing
Questo paragrafo ha un rientro di 2em sulla prima riga.
Testo con spaziatura tra le lettere.
Testo con spaziatura tra le parole.
8.5 line-height
Controlla l'altezza della riga. Fondamentale per la leggibilità: un valore tra 1.5 e 1.7 è l'ideale per il corpo del testo.
Line-height 1.1 — molto compatto, difficile da leggere su testi lunghi.
Line-height 1.6 — il valore ideale per il corpo del testo. Offre buona leggibilità senza sprecare spazio.
Line-height 2 — troppo arioso, adatto solo per titoli o citazioni.
8.6 text-shadow
Sintassi: text-shadow: offset-x offset-y blur color;
Ombra base
Glow blu
Ombra retro multipla
8.7 text-overflow: troncare il testo
Per troncare il testo con ..., servono tre proprietà insieme: white-space: nowrap, overflow: hidden e text-overflow: ellipsis.
.titolo { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 300px; }
8.8 Altre proprietà del testo
| Proprietà | Valori principali | Effetto |
|---|---|---|
white-space | normal, nowrap, pre, pre-wrap, pre-line | Gestione spazi e a capo |
word-break | normal, break-all, keep-all | Interruzione parole |
overflow-wrap | normal, break-word, anywhere | A capo parole lunghe |
hyphens | none, manual, auto | Sillabazione |
direction | ltr, rtl | Direzione testo |
writing-mode | horizontal-tb, vertical-rl, vertical-lr | Orientamento testo |
9Font Base
9.1 font-family
Definisce la famiglia tipografica. È buona norma specificare più font di fallback, in ordine di preferenza.
body { font-family: 'Sora', 'Helvetica Neue', Arial, sans-serif; } /* Generic families */ /* serif — con grazie (Times, Georgia) */ /* sans-serif — senza grazie (Arial, Helvetica) */ /* monospace — larghezza fissa (Courier, Consolas) */ /* cursive — corsivo (Comic Sans) */ /* fantasy — decorativo (Impact) */
9.2 font-size
Dimensione del testo. Puoi usare misure assolute (px) o relative (em, rem, %).
| Unità | Esempio | Quando usarla |
|---|---|---|
px | 16px | Misure fisse (raramente) |
rem | 1rem = 16px | Consigliata per font |
em | 1.5em | Proporzionale al genitore |
% | 150% | Come em |
clamp() | clamp(1rem, 2vw, 1.5rem) | Fluido (moderno) |
9.3 font-weight
Spessore del font. I valori vanno da 100 (thin) a 900 (black).
100 Thin
300 Light
400 Regular (default)
500 Medium
700 Bold
900 Black
9.4 font-style
.normal { font-style: normal; } .italic { font-style: italic; } .oblique { font-style: oblique 15deg; }
9.5 font shorthand
Puoi scrivere tutte le proprietà in una sola riga. L'ordine è obbligatorio: style weight size/line-height family.
.titolo { font: italic 700 2rem/1.2 'Sora', sans-serif; }
9.6 Google Fonts: come usare font personalizzati
Per usare un font personalizzato come "Inter" o "Sora", puoi collegarti a Google Fonts.
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"> body { font-family: 'Inter', system-ui, sans-serif; }
- Base 16px (1rem): minimo leggibile
- Line-height 1.5–1.7 per il corpo
- Max 70-75 caratteri per riga (
max-width: 65ch) - Massimo 2-3 font per progetto
10Link Base
Le pseudo-classi dei link si applicano in un ordine preciso, facilmente memorizzabile con l'acronimo LVHA: :link, :visited, :hover, :active.
a:link { color: #2E6FF2; text-decoration: none; } a:visited { color: #7C5CFC; } a:hover { color: #E8792E; text-decoration: underline; } a:active { color: #D6479B; }
La sottolineatura è il segnale visivo più riconoscibile. Se la togli, assicurati che il link abbia un colore diverso dal testo normale.
11Liste Base
Le liste (<ul>, <ol>) hanno proprietà specifiche per controllare i marker (pallini, numeri).
11.1 list-style-type
Definisce il tipo di marker. Valori comuni per <ul> e <ol>:
| Tipo | Valori |
|---|---|
| Unordered list (ul) | disc (default), circle, square, none |
| Ordered list (ol) | decimal (default), decimal-leading-zero, lower-roman, upper-roman, lower-alpha, upper-alpha, lower-greek |
| Altri | none (rimuove il marker) |
disc
- Primo
- Secondo
circle
- Primo
- Secondo
square
- Primo
- Secondo
upper-roman
- Primo
- Secondo
lower-alpha
- Primo
- Secondo
none
- Primo
- Secondo
11.2 list-style-position
Decide se il marker è dentro o fuori dal contenuto della lista.
outside (default)
- Il marker è fuori dal testo, allineato a sinistra
- Il testo è allineato verticalmente
inside
- Il marker è dentro il blocco di testo
- Il testo va a capo sotto il marker
11.3 list-style-image
Sostituisce il marker con un'immagine. Raramente usato perché poco controllabile.
ul { list-style-image: url('checkmark.svg'); }
11.4 list-style shorthand
ul { list-style: square inside; } ul.menu { list-style: none; }
11.5 ::marker
Il pseudo-elemento ::marker permette di stilizzare direttamente il marker della lista.
- Primo elemento con marker blu ← il marker è blu
- Secondo elemento ← il marker è blu
Con li::marker { color: #2E6FF2; }
12Tabelle Base
Le tabelle hanno proprietà specifiche che le rendono più leggibili. La più importante è border-collapse.
12.1 border-collapse
Di default i bordi delle celle sono separati (con spaziatura). Con collapse, i bordi si fondono in un'unica linea.
table { width: 100%; border-collapse: collapse; /* bordi uniti */ border-spacing: 0; /* spaziatura (se separate) */ } th { background: #142850; color: #fff; padding: 12px; text-align: left; } td { padding: 12px; border-bottom: 1px solid #E1E7F0; } tbody tr:nth-child(even) { background: #F7F9FC; } /* zebra */ tbody tr:hover { background: #E8F0FE; } /* hover */
| Nome | Cognome | Età |
|---|---|---|
| Mario | Rossi | 17 |
| Luca | Bianchi | 18 |
| Sofia | Verdi | 16 |
| Anna | Neri | 17 |
12.2 table-layout
Controlla come il browser calcola la larghezza delle colonne.
| Valore | Comportamento |
|---|---|
auto | Default. Si adatta al contenuto. |
fixed | Larghezze fisse, più veloce da renderizzare. |
12.3 caption-side
Posiziona il <caption> della tabella sopra o sotto.
caption { caption-side: bottom; }
13Display Base
La proprietà display è la più importante per il layout: definisce come un elemento si comporta nel flusso del documento.
| Valore | Comportamento | Esempi |
|---|---|---|
block | Va a capo, tutta la larghezza disponibile | div, p, h1, section |
inline | Nella riga, solo lo spazio necessario | span, a, strong, em |
inline-block | Come inline ma accetta width/height | bottoni, badge |
flex | Attiva Flexbox per i figli | navbar, card |
grid | Attiva Grid per i figli | layout pagina |
none | Nasconde completamente (fuori dal layout) | modali nascoste |
contents | L'elemento "scompare", i figli restano | wrapper trasparenti |
display: none→ scompare dal layout, non occupa spaziovisibility: hidden→ invisibile ma occupa spazio
14Position Base
La proprietà position controlla come un elemento è posizionato nella pagina. È una delle più potenti e confuse.
| Valore | Comportamento |
|---|---|
static | Default, nel flusso normale |
relative | Nel flusso, spostabile con top/right/bottom/left, riferimento per absolute |
absolute | Fuori dal flusso, rispetto al primo antenato positioned |
fixed | Fuori dal flusso, rispetto al viewport (non scorre) |
sticky | Relative poi fixed a una soglia di scroll |
14.1 position: absolute dentro relative
Il pattern più comune: un genitore con position: relative e un figlio con position: absolute. Il figlio si posiziona rispetto al genitore.
Il genitore ha position: relative. Il box rosa ha position: absolute.
.parent { position: relative; } .badge { position: absolute; top: 10px; right: 10px; } .sticky { position: sticky; top: 0; z-index: 100; } .fab { position: fixed; bottom: 20px; right: 20px; }
14.2 z-index
Quando due elementi si sovrappongono, z-index decide chi sta davanti. Funziona solo su elementi con position diversa da static.
.modal { position: fixed; z-index: 9999; /* sta davanti a tutto */ } .header { position: sticky; top: 0; z-index: 100; }
15Il Box Model Base
Ogni elemento HTML è una scatola rettangolare. Il Box Model descrive come questa scatola è composta, dall'interno verso l'esterno:
- Content: il contenuto vero e proprio (testo, immagine).
- Padding: lo spazio tra il contenuto e il bordo.
- Border: la linea di confine.
- Margin: lo spazio esterno, che separa l'elemento dagli altri.
15.1 box-sizing: la trappola da conoscere
Di default, se dai a un elemento width: 200px e padding: 20px, la sua larghezza totale sarà 240px (200 + 20 + 20). Questo perché il padding si aggiunge alla larghezza. La proprietà box-sizing: border-box cambia questo comportamento: la larghezza include padding e bordo.
Entrambi con width: 200px; padding: 20px; border: 5px:
/* Reset universale: SEMPRE all'inizio del tuo CSS */ *, *::before, *::after { box-sizing: border-box; }
15.2 box-shadow
Sintassi: box-shadow: offset-x offset-y blur spread color inset;
16Float e clear Base
float serviva per layout multi-colonna prima di Flex/Grid. Oggi si usa principalmente per far scorrere il testo attorno a un'immagine.
Il testo scorre attorno al box blu. Se è abbastanza lungo, continuerà sotto di esso. Questo è il comportamento tipico di un'immagine con testo che la circonda.
.float-img { float: left; margin-right: 1rem; } .clear { clear: both; } /* Clearfix tradizionale */ .clearfix::after { content: ""; display: table; clear: both; } /* Metodo moderno */ .clearfix { display: flow-root; }
Per layout multi-colonna usa Flexbox o Grid. Sono più potenti, prevedibili e non richiedono clearfix.
17Overflow Base
Cosa succede quando il contenuto è troppo grande per il suo contenitore? La proprietà overflow decide se mostrarlo, nasconderlo o aggiungere barre di scorrimento.
| Valore | Effetto |
|---|---|
visible | Default, il contenuto esce |
hidden | Tagliato |
scroll | Barre sempre visibili |
auto | Barre solo se servono |
clip | Come hidden senza scroll |
visible
hidden
scroll
auto
18Pseudo-classi Base
Le pseudo-classi selezionano elementi in uno stato particolare (es. quando il mouse ci passa sopra, quando un campo è a fuoco, quando un link è stato visitato). Sono scritte con i due punti :.
18.1 Pseudo-classi di stato
| Pseudo-classe | Seleziona... |
|---|---|
:hover | Elemento sotto il mouse |
:focus | Elemento a fuoco (input, button) |
:focus-visible | Focus da tastiera (non da mouse) |
:active | Elemento attivo (durante il click) |
:visited | Link già visitato |
:link | Link non ancora visitato |
:checked | Checkbox/radio selezionato |
:disabled | Elemento disabilitato |
:enabled | Elemento abilitato |
:required | Campo obbligatorio |
:valid / :invalid | Validità campo form |
a:hover { color: #E8A34E; text-decoration: underline; } input:focus { outline: 2px solid #2E6FF2; } button:active { transform: scale(.97); } input:checked + label { font-weight: 700; } input:disabled { opacity: .5; }
18.2 Pseudo-classi strutturali
| Pseudo-classe | Seleziona... |
|---|---|
:first-child | Primo figlio |
:last-child | Ultimo figlio |
:nth-child(n) | n-esimo figlio |
:nth-child(even) | Figli pari |
:nth-child(odd) | Figli dispari |
:nth-child(3n) | Ogni 3 figli |
:first-of-type | Primo elemento del suo tipo |
:last-of-type | Ultimo elemento del suo tipo |
:only-child | Unico figlio |
:empty | Elemento senza figli/testo |
li:first-child { font-weight: 700; } li:last-child { border-bottom: none; } li:nth-child(even) { background: #EEF2FA; } li:nth-child(3n) { color: red; }
18.3 Pseudo-classi di negazione
:not(...) esclude elementi che corrispondono al selettore passato.
p:not(.intro) { margin-top: 1rem; } button:not([disabled]) { cursor: pointer; }
18.4 Pseudo-classi avanzate (livello intermedio)
| Pseudo-classe | Descrizione |
|---|---|
:is(...) | Raggruppa selettori (riduce ripetizione) |
:where(...) | Come :is() ma con specificità 0 |
:has(...) | Seleziona il genitore in base al figlio (rivoluzionario) |
:focus-within | Genitore con figlio a fuoco |
/* :is() — raggruppa selettori */ :is(article, section) :is(h1, h2) { color: #142850; } /* :where() — come :is() ma specificità 0 */ :where(ul, ol) { padding-left: 1.5rem; } /* :has() — seleziona il genitore in base al figlio */ form:has(input:invalid) { border-color: red; } .card:has(img) { padding: 0; } /* :focus-within — genitore con figlio a fuoco */ fieldset:focus-within { border-color: #2E6FF2; background: #E8F0FE; }
19Pseudo-elementi Base
I pseudo-elementi creano "finti" elementi che non esistono nell'HTML. Sono scritti con due due punti :: (invece che uno).
| Pseudo-elemento | Uso |
|---|---|
::before | Contenuto prima (richiede content) |
::after | Contenuto dopo (richiede content) |
::first-line | Prima riga di testo |
::first-letter | Prima lettera (capolettera) |
::marker | Marker di lista |
::placeholder | Placeholder di input |
::selection | Testo selezionato dall'utente |
::backdrop | Sfondo di dialoghi fullscreen |
19.1 ::before e ::after
I più usati. Creano contenuto prima o dopo un elemento. Devono avere obbligatoriamente la proprietà content, anche solo content: "".
/* Freccia sui link esterni */ a[target="_blank"]::after { content: " ↗"; } /* Linea decorativa sotto h2 */ h2::after { content: ""; display: block; width: 40px; height: 3px; background: #2E6FF2; margin-top: .5rem; } /* Clearfix */ .clearfix::after { content: ""; display: table; clear: both; }
19.2 ::first-line e ::first-letter
Questo paragrafo ha un capolettera stilizzato con il pseudo-elemento ::first-letter. È un effetto tipico dei giornali e delle riviste.
19.3 ::marker
Stilizza il marker di una lista (pallino, numero).
li::marker { color: #2E6FF2; font-size: 1.5em; }
19.4 ::placeholder
input::placeholder { color: #9dabc2; font-style: italic; }
19.5 ::selection
Questo testo ha uno stile di selezione personalizzato: seleziona queste parole e vedrai il colore.
20Specificità e cascata Base
Quando due regole si applicano allo stesso elemento, vince quella con specificità maggiore. La specificità è calcolata come una specie di punteggio (a, b, c, d):
- a: stili inline (0 o 1)
- b: numero di
#id - c: numero di classi, pseudo-classi, attributi
- d: numero di tag e pseudo-elementi
| Selettore | Specificità |
|---|---|
* | (0,0,0,0) |
p | (0,0,0,1) |
.box | (0,0,1,0) |
nav a | (0,0,0,2) |
.box p | (0,0,1,1) |
#main .box p | (0,1,1,1) |
style="..." | (1,0,0,0) |
Se ti serve, c'è un problema di architettura. Usalo solo per override di terze parti o utility class.
★Esempi pratici · Base
Tre componenti completi che mettono insieme tutto il livello Base: card, menu di navigazione e layout di pagina.
Esempio 1 — Card
Una card riutilizzabile con immagine, titolo, testo e pulsante.
<article class="card"> <img src="foto.jpg" alt="Descrizione" class="card-img"> <div class="card-body"> <h3>Titolo card</h3> <p>Breve descrizione del contenuto della card.</p> <a href="#" class="btn">Scopri di più</a> </div> </article>
.card { background: #fff; border-radius: 12px; border: 1px solid #E1E7F0; overflow: hidden; max-width: 320px; transition: transform .2s, box-shadow .2s; } .card:hover { transform: translateY(-4px); box-shadow: 0 15px 30px -15px rgba(46,111,242,.4); } .card-img { width: 100%; height: 180px; object-fit: cover; display: block; } .card-body { padding: 1.2rem; } .card-body h3 { margin: 0 0 .5rem; color: #142850; } .card-body p { color: #566072; font-size: .9rem; margin-bottom: 1rem; } .btn { display: inline-block; padding: .5rem 1rem; background: #2E6FF2; color: #fff; text-decoration: none; border-radius: 6px; font-size: .85rem; transition: background .15s; } .btn:hover { background: #1e5bd6; }
Esempio 2 — Menu di navigazione
Logo a sinistra, voci a destra, hover e voce attiva, responsive su mobile.
.site-header { display: flex; justify-content: space-between; align-items: center; padding: 1rem 2rem; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,.05); } .logo { font-size: 1.3rem; font-weight: 800; color: #2E6FF2; text-decoration: none; } .menu { display: flex; gap: 1.5rem; list-style: none; margin: 0; padding: 0; } .menu a { color: #1B2733; text-decoration: none; font-weight: 600; padding: .4rem .8rem; border-radius: 8px; transition: background .15s, color .15s; } .menu a:hover { background: #E8F0FE; color: #2E6FF2; } .menu a.attivo { background: #2E6FF2; color: #fff; } @media (max-width: 640px) { .site-header { flex-direction: column; gap: 1rem; } .menu { flex-direction: column; text-align: center; } }
Esempio 3 — Layout di sito web
Header sticky, hero con gradiente, sezione contenuti e footer. Struttura base riutilizzabile.
/* Reset */ * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: system-ui, sans-serif; background: #F7F9FC; line-height: 1.6; } /* Header sticky */ .site-header { position: sticky; top: 0; z-index: 100; display: flex; justify-content: space-between; align-items: center; padding: 1rem 2rem; background: #fff; border-bottom: 1px solid #E1E7F0; } /* Hero */ .hero { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; min-height: 60vh; padding: 2rem; background: linear-gradient(135deg, #2E6FF2, #7C5CFC); color: #fff; } .hero h1 { font-size: clamp(1.8rem, 5vw, 3rem); margin-bottom: 1rem; } .hero .btn { display: inline-block; padding: .8rem 1.6rem; background: #fff; color: #2E6FF2; text-decoration: none; font-weight: 700; border-radius: 8px; transition: transform .2s; } /* Container + card */ .container { max-width: 1080px; margin: 0 auto; padding: 3rem 1.5rem; } .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; } /* Footer */ .site-footer { text-align: center; padding: 2rem 1.5rem; background: #1B2733; color: #9dabc2; font-size: .85rem; }
★20 esercizi · Livello Base
Prova prima da solo, poi apri la soluzione.
Collega un CSS esterno
Scrivi il tag per collegare style.css.
Soluzione
<link rel="stylesheet" href="style.css">
Seleziona p con classe intro
Stilizza solo i <p> con classe intro.
Soluzione
p.intro { color: #2E6FF2; }
Colore del titolo
Imposta h1 a #142850.
Soluzione
h1 { color: #142850; }
Font-size in rem
h1 a 2rem, p a 1rem.
Soluzione
h1 { font-size: 2rem; } p { font-size: 1rem; }
Sfondo sul body
Imposta sfondo #F7F9FC.
Soluzione
body { background-color: #F7F9FC; }
Immagine che copre
.hero con immagine di sfondo che copre, centrata, non ripetuta.
Soluzione
.hero { background: url('hero.jpg') center / cover no-repeat; }
Bordo tratteggiato
Bordo tratteggiato 2px viola.
Soluzione
.box { border: 2px dashed #7C5CFC; }
Angoli arrotondati
Raggio 12px su una card.
Soluzione
.card { border-radius: 12px; }
Padding misto
1rem verticale e 2rem orizzontale.
Soluzione
.section { padding: 1rem 2rem; }
Centrare container
Container max 960px centrato.
Soluzione
.container { max-width: 960px; margin: 0 auto; }
Testo centrato
Centra un paragrafo.
Soluzione
p { text-align: center; }
Maiuscolo
h2 tutti in maiuscolo.
Soluzione
h2 { text-transform: uppercase; }
Font Google
Carica Sora e usalo nel body.
Soluzione
<link href="...family=Sora&display=swap" rel="stylesheet"> body { font-family: 'Sora', sans-serif; }
Link senza sottolineatura
Rimuovi la sottolineatura.
Soluzione
a { text-decoration: none; }
Rimuovi pallini
Rimuovi i marker da una ul.
Soluzione
ul { list-style: none; padding: 0; }
Zebra striping
Colora le righe pari.
Soluzione
tbody tr:nth-child(even) { background: #F7F9FC; }
Span come block
Fai comportare uno span come blocco.
Soluzione
span.block { display: block; }
Badge in alto a destra
Badge posizionato in alto a destra dentro una card.
Soluzione
.card { position: relative; } .badge { position: absolute; top: 10px; right: 10px; }
Reset universale
box-sizing: border-box su tutto.
Soluzione
*, *::before, *::after { box-sizing: border-box; }
Nascondi overflow
Nascondi contenuto in eccesso in un box alto 100px.
Soluzione
.box { height: 100px; overflow: hidden; }
21Flexbox Intermedio
Sistema di layout monodimensionale (una riga o una colonna). Perfetto per navbar, card, centrare contenuti. Flexbox è diventato lo standard per la maggior parte dei layout moderni.
21.1 Proprietà del container
| Proprietà | Valori | Effetto |
|---|---|---|
display | flex | inline-flex | Attiva Flexbox |
flex-direction | row | column | row-reverse | column-reverse | Asse principale |
justify-content | flex-start | center | space-between | space-around | space-evenly | Distribuzione asse principale |
align-items | stretch | center | flex-start | flex-end | baseline | Allineamento asse trasversale |
gap | 1rem | Spazio tra i figli |
flex-wrap | nowrap | wrap | wrap-reverse | Va a capo |
21.2 flex-direction
La direzione principale. Di default è row (riga), ma puoi usare column per impilare verticalmente.
21.3 justify-content
Distribuisce gli elementi lungo l'asse principale (orizzontale se row, verticale se column).
21.4 align-items
Allinea gli elementi lungo l'asse trasversale (verticale se row, orizzontale se column).
21.5 Proprietà dei figli
| Proprietà | Significato |
|---|---|
flex | Shorthand grow/shrink/basis |
flex-grow | Quanto cresce |
flex-shrink | Quanto si restringe |
flex-basis | Dimensione di partenza |
align-self | Override di align-items |
order | Cambia ordine visivo |
flex: 1
Se dai flex: 1 a due figli, si dividono lo spazio equamente. Se lo dai solo a uno, occupa tutto lo spazio rimasto. Perfetto per sidebar + contenuto.
.navbar { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 1rem 2rem; }
22Responsive design Intermedio
Il responsive design permette a una pagina di adattarsi a qualsiasi dimensione di schermo (smartphone, tablet, desktop). È una competenza fondamentale: oltre il 60% del traffico web arriva da mobile.
22.1 Meta viewport
Il meta viewport è fondamentale per il responsive. Senza di esso, il browser mobile simula una larghezza desktop (es. 980px) e rimpicciolisce tutto.
<meta name="viewport" content="width=device-width, initial-scale=1.0">
22.2 Media query
Le media query permettono di applicare CSS diverso in base alle caratteristiche del dispositivo (larghezza, orientamento, preferenze).
/* Mobile-first: parti dal piccolo e aggiungi */ .container { padding: 1rem; } @media (min-width: 768px) { .container { padding: 2rem; } } @media (min-width: 1024px) { .container { max-width: 1080px; margin: 0 auto; } } /* Combinazioni */ @media (min-width: 768px) and (max-width: 1023px) { /* tablet */ } /* Preferenze utente */ @media (prefers-color-scheme: dark) { /* tema scuro */ } @media (prefers-reduced-motion: reduce) { /* disabilita animazioni */ } @media (orientation: landscape) { /* schermo orizzontale */ } @media (hover: hover) { /* dispositivo con mouse */ } @media (pointer: coarse) { /* touch screen */ }
| Breakpoint | Dispositivo |
|---|---|
< 480px | Smartphone verticale |
480 – 767px | Smartphone orizzontale |
768 – 1023px | Tablet |
1024 – 1439px | Desktop |
≥ 1440px | Desktop grande |
22.3 Immagini e testo responsive
img { max-width: 100%; height: auto; display: block; } h1 { font-size: clamp(1.5rem, 5vw, 3rem); } /* Immagini con art direction (browser moderni) */ <picture> <source media="(min-width: 768px)" srcset="grande.jpg"> <img src="piccola.jpg" alt="..."> </picture>
Parti da mobile e aggiungi con min-width. Se funziona su mobile, funziona ovunque. Le media query con min-width sono più facili da gestire di quelle con max-width.
23Transizioni Intermedio
Le transizioni rendono fluido il passaggio da uno stato all'altro. Invece di un cambiamento istantaneo, l'animazione avviene gradualmente.
23.1 Proprietà
| Proprietà | Esempio | Cosa fa |
|---|---|---|
transition-property | background | Cosa animare |
transition-duration | .3s | Durata |
transition-timing-function | ease-in-out | Curva temporale |
transition-delay | .1s | Ritardo |
transition | Shorthand | Tutto insieme |
/* transition: proprietà durata timing delay */ .btn { background: #2E6FF2; transition: background .2s ease-in-out; } /* Più proprietà */ .card { transition: transform .2s, box-shadow .3s; } /* Anima tutto (attento alle prestazioni) */ .link { transition: all .2s; }
| Timing | Effetto |
|---|---|
linear | Costante |
ease | Default |
ease-in | Lento → veloce |
ease-out | Veloce → lento |
ease-in-out | Lento ai lati |
cubic-bezier(...) | Personalizzata |
steps(n) | A scatti |
Sono le proprietà più performanti (gestite dalla GPU). width, height, margin, top/left causano reflow e sono più lente.
24Animazioni Intermedio
Le animazioni permettono di creare sequenze di trasformazioni nel tempo, controllate tramite @keyframes.
@keyframes spin { from { transform: rotate(0); } to { transform: rotate(360deg); } } .loader { width: 44px; height: 44px; border: 5px solid #E1E7F0; border-top-color: #2E6FF2; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .card { animation: fadeInUp .5s ease-out both; }
| Proprietà | Valori |
|---|---|
animation-name | spin |
animation-duration | 1s |
animation-timing-function | linear, ease |
animation-delay | .5s |
animation-iteration-count | 1, infinite |
animation-direction | normal, reverse, alternate |
animation-fill-mode | none, forwards, backwards, both |
animation-play-state | running, paused |
Rispetta le preferenze degli utenti che soffrono di disturbi vestibolari.
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }
25Variabili CSS Intermedio
Le variabili CSS (custom properties) permettono di riutilizzare valori in tutto il foglio di stile. Sono fondamentali per temi, palette colori e design system.
:root { --primary: #2E6FF2; --accent: #7C5CFC; --radius: 12px; --space: 1rem; } .btn { background: var(--primary); border-radius: var(--radius); padding: var(--space); } /* Fallback */ .box { color: var(--testo, black); } /* Scope locale: sovrascrive --primary solo dentro .box-verde */ .box-verde { --primary: #2FAE66; }
25.1 Tema scuro con un solo blocco
Le variabili CSS rendono il tema scuro estremamente semplice: basta riassegnare i valori in un blocco.
:root { --bg: #F7F9FC; --ink: #1B2733; } html[data-theme="dark"] { --bg: #0a1428; --ink: #e6ecf5; } body { background: var(--bg); color: var(--ink); transition: background .3s, color .3s; }
Usa variabili per colori, spaziature, radii, font. Cambiare un valore in un solo posto aggiornerà tutto il sito. È il principio dei "design token".
26Pseudo-classi avanzate Intermedio
Pseudo-classi moderne che risolvono problemi complessi in modo elegante.
| Pseudo-classe | Descrizione | Esempio |
|---|---|---|
:is(...) | Raggruppa selettori | :is(h1, h2, h3) { color: red; } |
:where(...) | Come :is() ma specificità 0 | :where(ul, ol) { padding: 0; } |
:has(...) | Seleziona il genitore in base al figlio | .card:has(img) { padding: 0; } |
:not(...) | Esclude elementi | p:not(.intro) { margin: 0; } |
:focus-visible | Focus da tastiera | button:focus-visible { outline: 2px solid blue; } |
:focus-within | Genitore con figlio a fuoco | fieldset:focus-within { border-color: blue; } |
:checked | Checkbox/radio selezionato | input:checked + label { font-weight: 700; } |
:disabled | Elemento disabilitato | button:disabled { opacity: .5; } |
:required | Campo obbligatorio | input:required { border-color: red; } |
:valid / :invalid | Validità campo | input:invalid { border-color: red; } |
:empty | Elemento vuoto | p:empty { display: none; } |
:target | Elemento bersaglio di un'ancora | :target { background: yellow; } |
/* :is() — riduce ripetizione */ :is(article, section) :is(h1, h2) { color: #142850; } /* :has() — selettore genitore (rivoluzionario) */ form:has(input:invalid) { border-color: red; } .card:has(img) { padding: 0; } /* :focus-visible — outline solo da tastiera */ button:focus-visible { outline: 3px solid #2E6FF2; outline-offset: 2px; } /* :focus-within — genitore con figlio a fuoco */ fieldset:focus-within { border-color: #2E6FF2; background: #E8F0FE; }
27Pseudo-elementi avanzati Intermedio
Oltre a ::before e ::after, ci sono altri pseudo-elementi utili in situazioni specifiche.
27.1 ::selection
Stilizza il testo selezionato dall'utente.
Questo testo ha uno stile di selezione personalizzato: seleziona queste parole e vedrai il colore.
27.2 ::placeholder
input::placeholder { color: #9dabc2; font-style: italic; }
27.3 ::marker
li::marker { color: #2E6FF2; font-size: 1.5em; }
27.4 ::backdrop
Stilizza lo sfondo di un dialogo fullscreen (es. <dialog>).
dialog::backdrop { background: rgba(0, 0, 0, .5); backdrop-filter: blur(4px); }
28Ombre e gradienti Intermedio
28.1 box-shadow
Sintassi: box-shadow: offset-x offset-y blur spread color inset;
28.2 text-shadow
Sintassi: text-shadow: offset-x offset-y blur color;
Ombra base
Glow blu
Ombra retro multipla
28.3 Gradienti
/* Lineare */ .a { background: linear-gradient(#2E6FF2, #7C5CFC); } .b { background: linear-gradient(135deg, #2E6FF2, #D6479B); } /* Radiale */ .c { background: radial-gradient(circle, #2E6FF2, #7C5CFC); } /* Conica */ .d { background: conic-gradient(#2E6FF2, #7C5CFC, #D6479B, #E8792E, #2E6FF2); } /* Testo con gradiente */ .gradient-text { background: linear-gradient(90deg, #2E6FF2, #7C5CFC); -webkit-background-clip: text; background-clip: text; color: transparent; }
29Trasformazioni Intermedio
Le trasformazioni modificano la posizione, la rotazione, la scala e l'inclinazione di un elemento, senza influire sul layout degli altri elementi.
| Funzione | Effetto |
|---|---|
translate(x, y) | Sposta |
translateX(x) | Sposta orizzontalmente |
translateY(y) | Sposta verticalmente |
rotate(deg) | Ruota |
scale(n) | Scala |
scaleX(n) / scaleY(n) | Scala su un asse |
skew(x, y) | Inclina |
matrix(...) | Trasformazione combinata |
.elemento { transform: translateX(20px) rotate(15deg) scale(1.1); transform-origin: top left; /* punto di origine */ }
Su <span> o <a> serve display: inline-block o block.
★Esempi pratici · Intermedio
Tre componenti reali che combinano Flexbox, transizioni, variabili e responsive.
Esempio 1 — Card di pricing
Tre piani di prezzo affiancati, con piano evidenziato al centro.
.pricing { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; max-width: 1000px; margin: 3rem auto; padding: 0 1.5rem; } .plan { position: relative; background: #fff; border: 1px solid #E1E7F0; border-radius: 12px; padding: 2rem 1.5rem; text-align: center; transition: transform .2s, box-shadow .2s; } .plan:hover { transform: translateY(-4px); box-shadow: 0 20px 40px -20px rgba(0,0,0,.2); } .plan--featured { border-color: #2E6FF2; box-shadow: 0 20px 40px -20px rgba(46,111,242,.5); transform: scale(1.03); } .plan .badge { position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: #2E6FF2; color: #fff; font-size: .75rem; font-weight: 700; padding: .3rem .8rem; border-radius: 999px; }
Base
9€/mese
5 progetti · 1 GB
Pro
19€/mese
Illimitati · 50 GB
Business
49€/mese
Tutto · 500 GB
Esempio 2 — Toggle tema scuro
Bottone che cambia tema con variabili CSS e transition.
:root { --bg: #F7F9FC; --ink: #1B2733; --surface: #fff; } html[data-theme="dark"] { --bg: #0a1428; --ink: #e6ecf5; --surface: #152040; } body { background: var(--bg); color: var(--ink); transition: background .3s, color .3s; }
const btn = document.getElementById('themeToggle'); const root = document.documentElement; btn.addEventListener('click', () => { const current = root.getAttribute('data-theme') || 'light'; root.setAttribute('data-theme', current === 'dark' ? 'light' : 'dark'); });
Esempio 3 — Menu hamburger animato
Icona che diventa X quando il menu si apre, con transizione delle barre.
.hamburger { width: 44px; height: 44px; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 6px; background: none; border: none; cursor: pointer; } .hamburger span { display: block; width: 26px; height: 3px; background: #1B2733; border-radius: 2px; transition: transform .3s, opacity .3s; } .hamburger.open span:nth-child(1) { transform: translateY(9px) rotate(45deg); } .hamburger.open span:nth-child(2) { opacity: 0; } .hamburger.open span:nth-child(3) { transform: translateY(-9px) rotate(-45deg); }
★20 esercizi · Livello Intermedio
Navbar con logo e menu
Logo a sinistra, voci a destra, centrati.
Soluzione
.navbar { display: flex; justify-content: space-between; align-items: center; }
Centra in tutta la pagina
Centra in sezione 100vh.
Soluzione
.hero { display: flex; justify-content: center; align-items: center; min-height: 100vh; }
Card con footer in fondo
Footer sempre in fondo.
Soluzione
.card { display: flex; flex-direction: column; min-height: 250px; } .card-body { flex: 1; }
Due colonne 30/70
Sidebar e main.
Soluzione
.layout { display: flex; gap: 1rem; } .sidebar { flex: 3; } .main { flex: 7; }
Media query tablet
Padding body 1rem → 2rem sopra 768px.
Soluzione
@media (min-width: 768px) { body { padding: 2rem; } }
Immagine responsive
Mai più larga del contenitore.
Soluzione
img { max-width: 100%; height: auto; }
Bottone hover animato
Colore + sollevamento + ombra, 0.2s.
Soluzione
.btn { transition: all .2s; } .btn:hover { background: #7C5CFC; transform: translateY(-3px); box-shadow: 0 10px 20px -8px #7C5CFC; }
Cerchio pulsante
Scala + opacità in 1.4s infinito.
Soluzione
@keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: .6; } } .pulse { width: 40px; height: 40px; background: #2FAE66; border-radius: 50%; animation: pulse 1.4s ease-in-out infinite; }
Fade-in con ritardo
Card che entra con dissolvenza e movimento.
Soluzione
@keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .card { animation: fadeIn .5s ease-out both; }
Palette custom properties
Definisci --primary e --bg.
Soluzione
:root { --primary: #2E6FF2; --bg: #F7F9FC; } body { background: var(--bg); } .btn { background: var(--primary); }
Tema scuro
Riassegna --bg e --ink in [data-theme="dark"].
Soluzione
html[data-theme="dark"] { --bg: #0a1428; --ink: #e6ecf5; }
:has() per form non valido
Bordo rosso se contiene input non valido.
Soluzione
form:has(input:invalid) { border: 2px solid #E2534D; }
:focus-visible
Outline solo da tastiera.
Soluzione
button:focus-visible { outline: 3px solid #2E6FF2; outline-offset: 2px; }
Freccia link esterni
↗ su target="_blank".
Soluzione
a[target="_blank"]::after { content: " ↗"; }
Linea sotto h2
Linea decorativa sotto i titoli.
Soluzione
h2::after { content: ""; display: block; width: 40px; height: 3px; background: #2E6FF2; margin-top: .5rem; }
Box-shadow card
Ombra morbida, più profonda al hover.
Soluzione
.card { box-shadow: 0 4px 12px rgba(0,0,0,.08); } .card:hover { box-shadow: 0 20px 40px rgba(0,0,0,.15); }
Bottone con gradiente
Gradiente lineare blu-viola.
Soluzione
.btn { background: linear-gradient(135deg, #2E6FF2, #7C5CFC); color: #fff; }
Testo con gradiente
Titolo con gradiente.
Soluzione
.gradient-text { background: linear-gradient(90deg, #2E6FF2, #7C5CFC); -webkit-background-clip: text; background-clip: text; color: transparent; }
Card che si alza
translateY(-4px) al hover.
Soluzione
.card { transition: transform .2s; } .card:hover { transform: translateY(-4px); }
Ruota icona
180° al hover.
Soluzione
.icon { transition: transform .3s; } .icon:hover { transform: rotate(180deg); }
22Responsive design Intermedio
Il responsive design permette a una pagina di adattarsi a qualsiasi dimensione di schermo (smartphone, tablet, desktop). È una competenza fondamentale: oltre il 60% del traffico web arriva da mobile.
22.1 Meta viewport
Il meta viewport è fondamentale per il responsive. Senza di esso, il browser mobile simula una larghezza desktop (es. 980px) e rimpicciolisce tutto.
<meta name="viewport" content="width=device-width, initial-scale=1.0">
22.2 Media query
Le media query permettono di applicare CSS diverso in base alle caratteristiche del dispositivo (larghezza, orientamento, preferenze).
/* Mobile-first: parti dal piccolo e aggiungi */ .container { padding: 1rem; } @media (min-width: 768px) { .container { padding: 2rem; } } @media (min-width: 1024px) { .container { max-width: 1080px; margin: 0 auto; } } /* Combinazioni */ @media (min-width: 768px) and (max-width: 1023px) { /* tablet */ } /* Preferenze utente */ @media (prefers-color-scheme: dark) { /* tema scuro */ } @media (prefers-reduced-motion: reduce) { /* disabilita animazioni */ } @media (orientation: landscape) { /* schermo orizzontale */ } @media (hover: hover) { /* dispositivo con mouse */ } @media (pointer: coarse) { /* touch screen */ }
| Breakpoint | Dispositivo |
|---|---|
< 480px | Smartphone verticale |
480 – 767px | Smartphone orizzontale |
768 – 1023px | Tablet |
1024 – 1439px | Desktop |
≥ 1440px | Desktop grande |
22.3 Immagini e testo responsive
img { max-width: 100%; height: auto; display: block; } h1 { font-size: clamp(1.5rem, 5vw, 3rem); } /* Immagini con art direction (browser moderni) */ <picture> <source media="(min-width: 768px)" srcset="grande.jpg"> <img src="piccola.jpg" alt="..."> </picture>
Parti da mobile e aggiungi con min-width. Se funziona su mobile, funziona ovunque. Le media query con min-width sono più facili da gestire di quelle con max-width.
23Transizioni Intermedio
Le transizioni rendono fluido il passaggio da uno stato all'altro. Invece di un cambiamento istantaneo, l'animazione avviene gradualmente.
23.1 Proprietà
| Proprietà | Esempio | Cosa fa |
|---|---|---|
transition-property | background | Cosa animare |
transition-duration | .3s | Durata |
transition-timing-function | ease-in-out | Curva temporale |
transition-delay | .1s | Ritardo |
transition | Shorthand | Tutto insieme |
/* transition: proprietà durata timing delay */ .btn { background: #2E6FF2; transition: background .2s ease-in-out; } /* Più proprietà */ .card { transition: transform .2s, box-shadow .3s; } /* Anima tutto (attento alle prestazioni) */ .link { transition: all .2s; }
| Timing | Effetto |
|---|---|
linear | Costante |
ease | Default |
ease-in | Lento → veloce |
ease-out | Veloce → lento |
ease-in-out | Lento ai lati |
cubic-bezier(...) | Personalizzata |
steps(n) | A scatti |
Sono le proprietà più performanti (gestite dalla GPU). width, height, margin, top/left causano reflow e sono più lente.
24Animazioni Intermedio
Le animazioni permettono di creare sequenze di trasformazioni nel tempo, controllate tramite @keyframes.
@keyframes spin { from { transform: rotate(0); } to { transform: rotate(360deg); } } .loader { width: 44px; height: 44px; border: 5px solid #E1E7F0; border-top-color: #2E6FF2; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .card { animation: fadeInUp .5s ease-out both; }
| Proprietà | Valori |
|---|---|
animation-name | spin |
animation-duration | 1s |
animation-timing-function | linear, ease |
animation-delay | .5s |
animation-iteration-count | 1, infinite |
animation-direction | normal, reverse, alternate |
animation-fill-mode | none, forwards, backwards, both |
animation-play-state | running, paused |
Rispetta le preferenze degli utenti che soffrono di disturbi vestibolari.
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }
25Variabili CSS Intermedio
Le variabili CSS (custom properties) permettono di riutilizzare valori in tutto il foglio di stile. Sono fondamentali per temi, palette colori e design system.
:root { --primary: #2E6FF2; --accent: #7C5CFC; --radius: 12px; --space: 1rem; } .btn { background: var(--primary); border-radius: var(--radius); padding: var(--space); } /* Fallback */ .box { color: var(--testo, black); } /* Scope locale: sovrascrive --primary solo dentro .box-verde */ .box-verde { --primary: #2FAE66; }
25.1 Tema scuro con un solo blocco
Le variabili CSS rendono il tema scuro estremamente semplice: basta riassegnare i valori in un blocco.
:root { --bg: #F7F9FC; --ink: #1B2733; } html[data-theme="dark"] { --bg: #0a1428; --ink: #e6ecf5; } body { background: var(--bg); color: var(--ink); transition: background .3s, color .3s; }
Usa variabili per colori, spaziature, radii, font. Cambiare un valore in un solo posto aggiornerà tutto il sito. È il principio dei "design token".
26Pseudo-classi avanzate Intermedio
Pseudo-classi moderne che risolvono problemi complessi in modo elegante.
| Pseudo-classe | Descrizione | Esempio |
|---|---|---|
:is(...) | Raggruppa selettori | :is(h1, h2, h3) { color: red; } |
:where(...) | Come :is() ma specificità 0 | :where(ul, ol) { padding: 0; } |
:has(...) | Seleziona il genitore in base al figlio | .card:has(img) { padding: 0; } |
:not(...) | Esclude elementi | p:not(.intro) { margin: 0; } |
:focus-visible | Focus da tastiera | button:focus-visible { outline: 2px solid blue; } |
:focus-within | Genitore con figlio a fuoco | fieldset:focus-within { border-color: blue; } |
:checked | Checkbox/radio selezionato | input:checked + label { font-weight: 700; } |
:disabled | Elemento disabilitato | button:disabled { opacity: .5; } |
:required | Campo obbligatorio | input:required { border-color: red; } |
:valid / :invalid | Validità campo | input:invalid { border-color: red; } |
:empty | Elemento vuoto | p:empty { display: none; } |
:target | Elemento bersaglio di un'ancora | :target { background: yellow; } |
/* :is() — riduce ripetizione */ :is(article, section) :is(h1, h2) { color: #142850; } /* :has() — selettore genitore (rivoluzionario) */ form:has(input:invalid) { border-color: red; } .card:has(img) { padding: 0; } /* :focus-visible — outline solo da tastiera */ button:focus-visible { outline: 3px solid #2E6FF2; outline-offset: 2px; } /* :focus-within — genitore con figlio a fuoco */ fieldset:focus-within { border-color: #2E6FF2; background: #E8F0FE; }
27Pseudo-elementi avanzati Intermedio
Oltre a ::before e ::after, ci sono altri pseudo-elementi utili in situazioni specifiche.
27.1 ::selection
Stilizza il testo selezionato dall'utente.
Questo testo ha uno stile di selezione personalizzato: seleziona queste parole e vedrai il colore.
27.2 ::placeholder
input::placeholder { color: #9dabc2; font-style: italic; }
27.3 ::marker
li::marker { color: #2E6FF2; font-size: 1.5em; }
27.4 ::backdrop
Stilizza lo sfondo di un dialogo fullscreen (es. <dialog>).
dialog::backdrop { background: rgba(0, 0, 0, .5); backdrop-filter: blur(4px); }
28Ombre e gradienti Intermedio
28.1 box-shadow
Sintassi: box-shadow: offset-x offset-y blur spread color inset;
28.2 text-shadow
Sintassi: text-shadow: offset-x offset-y blur color;
Ombra base
Glow blu
Ombra retro multipla
28.3 Gradienti
/* Lineare */ .a { background: linear-gradient(#2E6FF2, #7C5CFC); } .b { background: linear-gradient(135deg, #2E6FF2, #D6479B); } /* Radiale */ .c { background: radial-gradient(circle, #2E6FF2, #7C5CFC); } /* Conica */ .d { background: conic-gradient(#2E6FF2, #7C5CFC, #D6479B, #E8792E, #2E6FF2); } /* Testo con gradiente */ .gradient-text { background: linear-gradient(90deg, #2E6FF2, #7C5CFC); -webkit-background-clip: text; background-clip: text; color: transparent; }
29Trasformazioni Intermedio
Le trasformazioni modificano la posizione, la rotazione, la scala e l'inclinazione di un elemento, senza influire sul layout degli altri elementi.
| Funzione | Effetto |
|---|---|
translate(x, y) | Sposta |
translateX(x) | Sposta orizzontalmente |
translateY(y) | Sposta verticalmente |
rotate(deg) | Ruota |
scale(n) | Scala |
scaleX(n) / scaleY(n) | Scala su un asse |
skew(x, y) | Inclina |
matrix(...) | Trasformazione combinata |
.elemento { transform: translateX(20px) rotate(15deg) scale(1.1); transform-origin: top left; /* punto di origine */ }
Su <span> o <a> serve display: inline-block o block.
★Esempi pratici · Intermedio
Tre componenti reali che combinano Flexbox, transizioni, variabili e responsive.
Esempio 1 — Card di pricing
Tre piani di prezzo affiancati, con piano evidenziato al centro.
.pricing { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; max-width: 1000px; margin: 3rem auto; padding: 0 1.5rem; } .plan { position: relative; background: #fff; border: 1px solid #E1E7F0; border-radius: 12px; padding: 2rem 1.5rem; text-align: center; transition: transform .2s, box-shadow .2s; } .plan:hover { transform: translateY(-4px); box-shadow: 0 20px 40px -20px rgba(0,0,0,.2); } .plan--featured { border-color: #2E6FF2; box-shadow: 0 20px 40px -20px rgba(46,111,242,.5); transform: scale(1.03); } .plan .badge { position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: #2E6FF2; color: #fff; font-size: .75rem; font-weight: 700; padding: .3rem .8rem; border-radius: 999px; }
Base
9€/mese
5 progetti · 1 GB
Pro
19€/mese
Illimitati · 50 GB
Business
49€/mese
Tutto · 500 GB
Esempio 2 — Toggle tema scuro
Bottone che cambia tema con variabili CSS e transition.
:root { --bg: #F7F9FC; --ink: #1B2733; --surface: #fff; } html[data-theme="dark"] { --bg: #0a1428; --ink: #e6ecf5; --surface: #152040; } body { background: var(--bg); color: var(--ink); transition: background .3s, color .3s; }
const btn = document.getElementById('themeToggle'); const root = document.documentElement; btn.addEventListener('click', () => { const current = root.getAttribute('data-theme') || 'light'; root.setAttribute('data-theme', current === 'dark' ? 'light' : 'dark'); });
Esempio 3 — Menu hamburger animato
Icona che diventa X quando il menu si apre, con transizione delle barre.
.hamburger { width: 44px; height: 44px; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 6px; background: none; border: none; cursor: pointer; } .hamburger span { display: block; width: 26px; height: 3px; background: #1B2733; border-radius: 2px; transition: transform .3s, opacity .3s; } .hamburger.open span:nth-child(1) { transform: translateY(9px) rotate(45deg); } .hamburger.open span:nth-child(2) { opacity: 0; } .hamburger.open span:nth-child(3) { transform: translateY(-9px) rotate(-45deg); }
★20 esercizi · Livello Intermedio
Navbar con logo e menu
Logo a sinistra, voci a destra, centrati.
Soluzione
.navbar { display: flex; justify-content: space-between; align-items: center; }
Centra in tutta la pagina
Centra in sezione 100vh.
Soluzione
.hero { display: flex; justify-content: center; align-items: center; min-height: 100vh; }
Card con footer in fondo
Footer sempre in fondo.
Soluzione
.card { display: flex; flex-direction: column; min-height: 250px; } .card-body { flex: 1; }
Due colonne 30/70
Sidebar e main.
Soluzione
.layout { display: flex; gap: 1rem; } .sidebar { flex: 3; } .main { flex: 7; }
Media query tablet
Padding body 1rem → 2rem sopra 768px.
Soluzione
@media (min-width: 768px) { body { padding: 2rem; } }
Immagine responsive
Mai più larga del contenitore.
Soluzione
img { max-width: 100%; height: auto; }
Bottone hover animato
Colore + sollevamento + ombra, 0.2s.
Soluzione
.btn { transition: all .2s; } .btn:hover { background: #7C5CFC; transform: translateY(-3px); box-shadow: 0 10px 20px -8px #7C5CFC; }
Cerchio pulsante
Scala + opacità in 1.4s infinito.
Soluzione
@keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.2); opacity: .6; } } .pulse { width: 40px; height: 40px; background: #2FAE66; border-radius: 50%; animation: pulse 1.4s ease-in-out infinite; }
Fade-in con ritardo
Card che entra con dissolvenza e movimento.
Soluzione
@keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .card { animation: fadeIn .5s ease-out both; }
Palette custom properties
Definisci --primary e --bg.
Soluzione
:root { --primary: #2E6FF2; --bg: #F7F9FC; } body { background: var(--bg); } .btn { background: var(--primary); }
Tema scuro
Riassegna --bg e --ink in [data-theme="dark"].
Soluzione
html[data-theme="dark"] { --bg: #0a1428; --ink: #e6ecf5; }
:has() per form non valido
Bordo rosso se contiene input non valido.
Soluzione
form:has(input:invalid) { border: 2px solid #E2534D; }
:focus-visible
Outline solo da tastiera.
Soluzione
button:focus-visible { outline: 3px solid #2E6FF2; outline-offset: 2px; }
Freccia link esterni
↗ su target="_blank".
Soluzione
a[target="_blank"]::after { content: " ↗"; }
Linea sotto h2
Linea decorativa sotto i titoli.
Soluzione
h2::after { content: ""; display: block; width: 40px; height: 3px; background: #2E6FF2; margin-top: .5rem; }
Box-shadow card
Ombra morbida, più profonda al hover.
Soluzione
.card { box-shadow: 0 4px 12px rgba(0,0,0,.08); } .card:hover { box-shadow: 0 20px 40px rgba(0,0,0,.15); }
Bottone con gradiente
Gradiente lineare blu-viola.
Soluzione
.btn { background: linear-gradient(135deg, #2E6FF2, #7C5CFC); color: #fff; }
Testo con gradiente
Titolo con gradiente.
Soluzione
.gradient-text { background: linear-gradient(90deg, #2E6FF2, #7C5CFC); -webkit-background-clip: text; background-clip: text; color: transparent; }
Card che si alza
translateY(-4px) al hover.
Soluzione
.card { transition: transform .2s; } .card:hover { transform: translateY(-4px); }
Ruota icona
180° al hover.
Soluzione
.icon { transition: transform .3s; } .icon:hover { transform: rotate(180deg); }
30CSS Grid Avanzato
CSS Grid è un sistema di layout bidimensionale: gestisce righe e colonne insieme. È lo strumento più potente per creare layout complessi come dashboard, gallerie fotografiche, pagine di riviste.
30.1 Proprietà principali
| Proprietà | Valori | Effetto |
|---|---|---|
display | grid | inline-grid | Attiva Grid |
grid-template-columns | 1fr 1fr, repeat(3,1fr) | Definisce le colonne |
grid-template-rows | auto 1fr auto | Definisce le righe |
gap | 1rem | Spazio tra celle |
grid-column | span 2, 1 / 3 | Occupazione colonne |
grid-row | span 2, 1 / 3 | Occupazione righe |
grid-template-areas | Stringhe ASCII | Layout nominati |
justify-items | stretch, center, start, end | Allineamento orizzontale celle |
align-items | stretch, center, start, end | Allineamento verticale celle |
30.2 Griglia a 3 colonne
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
30.3 Griglia asimmetrica
30.4 Griglia responsive automatica
Il pattern più utile: auto-fill o auto-fit con minmax() crea una griglia che si adatta automaticamente alla larghezza disponibile.
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1.2rem; } /* auto-fit: le colonne vuote collassano */ .cards-fit { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
30.5 Layout con grid-template-areas
Questo è il modo più leggibile per creare layout complessi. Ogni stringa rappresenta una riga, e i nomi definiscono le aree.
.layout { display: grid; grid-template-areas: "header header" "sidebar main" "footer footer"; grid-template-columns: 260px 1fr; grid-template-rows: auto 1fr auto; gap: 1rem; min-height: 100vh; } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .main { grid-area: main; } .footer { grid-area: footer; }
- Flexbox: layout monodimensionali (navbar, card, form, righe o colonne singole)
- Grid: layout bidimensionali (pagine intere, gallerie, dashboard, righe E colonne)
- Combinati: Grid per la struttura della pagina, Flexbox per i componenti interni
31Funzioni CSS Avanzato
31.1 calc(): calcoli dinamici
La funzione calc() permette di eseguire calcoli matematici mescolando unità diverse.
.content { width: calc(100% - 250px); } h1 { font-size: calc(1.5rem + 2vw); } .modal { width: 600px; left: calc(50% - 300px); }
31.2 clamp(): minimo, preferito, massimo
h1 { font-size: clamp(1rem, 5vw, 2rem); } .section { padding: clamp(1rem, 3vw, 3rem); } .container { width: clamp(320px, 90%, 1200px); }
Titolo fluido con clamp()
Questo titolo si adatta: mai meno di 1rem, mai più di 2.5rem.
31.3 min() e max()
.card { width: min(300px, 100%); } .hero { padding: max(2rem, 5vw); }
31.4 var() con fallback
.btn { background: var(--primary, blue); } .box { color: var(--custom, var(--primary, #000)); }
32Proprietà moderne Avanzato
32.1 aspect-ratio
Mantiene un rapporto fisso tra larghezza e altezza. Fondamentale per video, immagini, avatar.
.video { aspect-ratio: 16 / 9; width: 100%; } .avatar { aspect-ratio: 1 / 1; width: 80px; border-radius: 50%; }
32.2 object-fit
Controlla come un'immagine o un video si adatta al suo contenitore.
| Valore | Effetto |
|---|---|
fill | Default, stira |
cover | Riempie, ritaglia |
contain | Mostra tutto, con spazi |
none | Originale |
scale-down | Il minore tra none/contain |
32.3 scroll-snap
Crea caroselli che si "agganciano" a posizioni precise durante lo scorrimento.
.carousel { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: 1rem; } .carousel > * { scroll-snap-align: center; flex-shrink: 0; width: 80%; }
32.4 backdrop-filter: l'effetto vetro
.glass { background: rgba(255 255 255 / .15); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,.3); }
32.5 Container queries
Come le media query ma basate sulla dimensione del contenitore, non del viewport.
.card-wrapper { container-type: inline-size; container-name: card; } @container card (min-width: 400px) { .card { display: grid; grid-template-columns: 120px 1fr; } }
32.6 Proprietà logiche
.b { margin-inline-start: 1rem; padding-block-start: 2rem; margin-inline: 1rem 2rem; margin-block: 1rem; inset: 0; }
33Prestazioni e ottimizzazione Avanzato
Non tutte le proprietà CSS sono uguali in termini di prestazioni. Alcune sono gestite dalla GPU (veloci), altre causano ricalcoli del layout (lente).
| Proprietà | Costo | Note |
|---|---|---|
transform, opacity | Basso | Solo GPU, molto veloce |
color, background-color | Medio | Solo repaint |
width, height, margin | Alto | Reflow completo |
top, left | Alto | Reflow |
Preferisci transform: translateY(-5px) invece di margin-top: -5px. Il primo è gestito dalla GPU, il secondo causa un ricalcolo del layout.
33.1 Ottimizzazione web font
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="...family=Inter:wght@400;700&display=swap" rel="stylesheet"> <link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
33.2 Contenuto fuori schermo
La proprietà content-visibility permette al browser di saltare il rendering delle sezioni non visibili.
.section-lunga { content-visibility: auto; contain-intrinsic-size: 0 500px; }
34Architettura CSS Avanzato
34.1 Naming: BEM
BEM (Block Element Modifier) è una convenzione di naming che rende il CSS più leggibile e manutenibile.
/* Blocco */ .card { /* ... */ } /* Elemento (doppio underscore) */ .card__title { /* ... */ } .card__body { /* ... */ } /* Modificatore (doppio trattino) */ .card--featured { /* ... */ }
34.2 Struttura file CSS
/* 1. RESET E VARIABILI */ /* 2. BASE (tipografia, body) */ /* 3. LAYOUT (container, grid pagina) */ /* 4. COMPONENTI (bottoni, card, form) */ /* 5. UTILITY (classi monouso) */ /* 6. MEDIA QUERY (mobile-first) */
34.3 Utility-first vs component-first
component
.card, .btn-primary, .navbar
HTML pulito, CSS più lungo. Es. Bootstrap, BEM.
utility
.p-4, .text-center, .bg-blue
HTML verboso, CSS corto. Es. Tailwind.
- Una responsabilità per classe
- Specificità più bassa possibile
- Evita !important e #id per lo stile
- Commenta a blocchi
- Variabili per colori, spazi, font
35Best practice Avanzato
Mobile-first
Parti dal piccolo e aggiungi con min-width.
Organizza il CSS
Sezioni con commenti.
Classi, non id
Riutilizzabili e specificità bassa.
Evita !important
Se serve, c'è un problema.
border-box
Sempre, su tutto.
Variabili
Un solo posto per i colori.
Accessibilità
Contrasto, focus, reduced-motion.
Commenta a blocchi
Non riga per riga.
Testa su mobile
320, 375, 768, 1280px.
★Esempi pratici · Avanzato
Esempio 1 — Dashboard con Grid
Layout completo con sidebar, topbar e area contenuti.
.dashboard { display: grid; grid-template-areas: "sidebar topbar" "sidebar content"; grid-template-columns: 240px 1fr; grid-template-rows: 60px 1fr; min-height: 100vh; gap: 1rem; padding: 1rem; background: #F7F9FC; } .sidebar { grid-area: sidebar; background: #142850; border-radius: 12px; padding: 1.5rem; color: #fff; } .topbar { grid-area: topbar; background: #fff; border-radius: 12px; padding: 1rem 1.5rem; display: flex; justify-content: space-between; align-items: center; } .content { grid-area: content; background: #fff; border-radius: 12px; padding: 1.5rem; } @media (max-width: 768px) { .dashboard { grid-template-areas: "topbar" "content" "sidebar"; grid-template-columns: 1fr; grid-template-rows: auto auto auto; } }
Esempio 2 — Galleria portfolio
Griglia fotografica con pattern masonry semplificato.
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-auto-rows: 200px; gap: 1rem; } /* Alcuni item occupano 2 righe */ .gallery > :nth-child(3n) { grid-row: span 2; } .gallery > :nth-child(5n) { grid-column: span 2; } .gallery img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; transition: transform .3s; } .gallery img:hover { transform: scale(1.05); }
Esempio 3 — Card con container query
Card che cambia layout in base alla larghezza del contenitore.
.card-wrapper { container-type: inline-size; } .card { display: flex; flex-direction: column; gap: 1rem; padding: 1.2rem; background: #fff; border-radius: 12px; border: 1px solid #E1E7F0; } @container (min-width: 400px) { .card { flex-direction: row; align-items: center; } .card img { width: 120px; height: 120px; } }
★20 esercizi · Livello Avanzato
3 colonne uguali
Grid con 3 colonne e gap 1rem.
Soluzione
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
Griglia responsive automatica
Min 250px per card.
Soluzione
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1rem; }
Item largo 2 colonne
Primo elemento span 2.
Soluzione
.grid { grid-template-columns: repeat(3, 1fr); } .grid > :first-child { grid-column: span 2; }
Layout con aree
Header, sidebar, main, footer.
Soluzione
.layout { display: grid; grid-template-areas: "header header" "sidebar main" "footer footer"; grid-template-columns: 200px 1fr; }
Layout pagina intera
Main che si allarga.
Soluzione
.page { display: grid; grid-template-rows: auto 1fr auto; min-height: 100vh; }
calc() per larghezza
100% meno 250px.
Soluzione
.content { width: calc(100% - 250px); }
Titolo fluido
Font tra 2rem e 4rem.
Soluzione
h1 { font-size: clamp(2rem, 5vw, 4rem); }
Padding fluido
1rem → 3rem.
Soluzione
.section { padding: clamp(1rem, 3vw, 3rem); }
Video 16:9
Rapporto aspetto.
Soluzione
.video { aspect-ratio: 16 / 9; width: 100%; }
Avatar con object-fit
Immagine senza distorsioni.
Soluzione
.avatar { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; }
Scroll-snap orizzontale
Carousel che si aggancia.
Soluzione
.carousel { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; } .carousel > * { scroll-snap-align: center; flex-shrink: 0; }
Container query
Card che cambia layout se contenitore > 400px.
Soluzione
.wrapper { container-type: inline-size; } @container (min-width: 400px) { .card { display: grid; grid-template-columns: 120px 1fr; } }
Proprietà logiche
margin-inline e padding-block.
Soluzione
.box { margin-inline: 1rem; padding-block: 2rem; }
Effetto vetro
backdrop-filter blur.
Soluzione
.glass { background: rgba(255 255 255 / .15); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,.3); }
content-visibility
Saltare rendering fuori schermo.
Soluzione
.section-lunga { content-visibility: auto; contain-intrinsic-size: 0 500px; }
Anima con transform
Sollevamento senza margin.
Soluzione
.card { transition: transform .2s; } .card:hover { transform: translateY(-4px); }
Naming BEM
Riscrivi in BEM: .card-title, .card-featured.
Soluzione
.card__title { /* ... */ } .card--featured { /* ... */ }
Design token
Variabili per spaziature e radius.
Soluzione
:root { --space-sm: .5rem; --space-md: 1rem; --space-lg: 2rem; --radius-sm: 6px; --radius-md: 12px; }
Dashboard Grid
Sidebar + topbar + contenuto.
Soluzione
.dashboard { display: grid; grid-template-areas: "sidebar topbar" "sidebar content"; grid-template-columns: 240px 1fr; grid-template-rows: 60px 1fr; min-height: 100vh; }
Galleria masonry
Grid con item che occupano più righe.
Soluzione
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); grid-auto-rows: 180px; gap: .8rem; } .gallery > :nth-child(3n) { grid-row: span 2; }
36Progetto finale
Costruisci un sito portfolio personale responsive con tema chiaro/scuro. Perfetto per l'esame di stato.
- Layout con CSS Grid (header / main / footer)
- Componenti con Flexbox (navbar, card, form)
- Variabili CSS per tema chiaro/scuro
- Responsive mobile-first
- Transizioni e animazioni di ingresso
- Accessibilità: contrasto, focus, prefers-reduced-motion
Requisiti
- Header: nome + navbar con 3 link, sticky in alto
- Hero: titolo gradiente, sottotitolo, bottone CTA
- Sezione "Progetti": griglia responsive di card
- Sezione "Contatti": form con nome, email, messaggio
- Footer: copyright centrato
- Tema scuro: bottone toggle
- Responsive: da 320px in su
Struttura file
portfolio/ ├── index.html ├── css/ │ └── style.css └── img/
Soluzione HTML
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Portfolio — Mario Rossi</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <header class="site-header"> <a href="#" class="logo">Mario Rossi</a> <nav> <a href="#progetti">Progetti</a> <a href="#contatti">Contatti</a> <button id="themeToggle" type="button" aria-label="Cambia tema">🌓</button> </nav> </header> <section class="hero"> <h1>Ciao, sono <span class="accent">Mario</span></h1> <p>Studente di informatica, appassionato di sviluppo web.</p> <a href="#progetti" class="btn">Vedi i miei progetti</a> </section> <main> <section id="progetti"> <h2>Progetti</h2> <div class="cards"> <article class="card"> <h3>To-do list</h3> <p>App per gestire attività con localStorage.</p> </article> <article class="card"> <h3>Meteo API</h3> <p>Ricerca meteo per città con API REST.</p> </article> <article class="card"> <h3>Quiz interattivo</h3> <p>Quiz a risposta multipla con punteggio.</p> </article> </div> </section> <section id="contatti"> <h2>Contattami</h2> <form class="contact-form"> <label for="nome">Nome</label> <input type="text" id="nome" required> <label for="email">Email</label> <input type="email" id="email" required> <label for="msg">Messaggio</label> <textarea id="msg" rows="5" required></textarea> <button type="submit" class="btn">Invia</button> </form> </section> </main> <footer class="site-footer"> <p>© 2026 Mario Rossi</p> </footer> <script> const btn = document.getElementById('themeToggle'); const root = document.documentElement; btn.addEventListener('click', () => { const current = root.getAttribute('data-theme') || 'light'; root.setAttribute('data-theme', current === 'dark' ? 'light' : 'dark'); }); </script> </body> </html>
Soluzione CSS
/* ============================================================ 1. RESET E VARIABILI ============================================================ */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } :root { --bg: #F7F9FC; --surface: #FFFFFF; --ink: #1B2733; --ink-soft: #566072; --primary: #2E6FF2; --accent: #7C5CFC; --border: #E1E7F0; --radius: 12px; --max: 1080px; } html[data-theme="dark"] { --bg: #0a1428; --surface: #152040; --ink: #e6ecf5; --ink-soft: #9dabc2; --border: #253557; } /* ============================================================ 2. BASE ============================================================ */ body { font-family: system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--ink); line-height: 1.6; transition: background .2s, color .2s; } h1, h2, h3 { line-height: 1.2; } a { color: var(--primary); text-decoration: none; } /* ============================================================ 3. LAYOUT ============================================================ */ .site-header, main, .site-footer, .hero { max-width: var(--max); margin: 0 auto; padding: 1rem 1.5rem; } /* ============================================================ 4. HEADER ============================================================ */ .site-header { display: flex; justify-content: space-between; align-items: center; position: sticky; top: 0; background: var(--surface); border-bottom: 1px solid var(--border); z-index: 100; } .site-header nav { display: flex; gap: 1.2rem; align-items: center; } .logo { font-weight: 700; font-size: 1.1rem; color: var(--ink); } /* ============================================================ 5. HERO ============================================================ */ .hero { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; min-height: 60vh; gap: 1.2rem; } .hero h1 { font-size: clamp(2rem, 5vw, 3rem); } .accent { background: linear-gradient(90deg, var(--primary), var(--accent)); -webkit-background-clip: text; background-clip: text; color: transparent; } /* ============================================================ 6. BOTTONE ============================================================ */ .btn { display: inline-block; background: var(--primary); color: #fff; padding: .75rem 1.4rem; border: none; border-radius: var(--radius); font-weight: 600; cursor: pointer; transition: transform .15s, background .15s, box-shadow .15s; } .btn:hover { background: var(--accent); transform: translateY(-2px); box-shadow: 0 10px 20px -8px var(--accent); } /* ============================================================ 7. CARDS ============================================================ */ main section { padding: 3rem 1.5rem; } main h2 { font-size: 1.8rem; margin-bottom: 1.5rem; } .cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1.2rem; } .card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.5rem; transition: transform .2s, box-shadow .2s, border-color .2s; } .card:hover { transform: translateY(-4px); border-color: var(--primary); box-shadow: 0 15px 30px -15px rgba(46,111,242,.4); } .card h3 { margin-bottom: .5rem; } .card p { color: var(--ink-soft); } /* ============================================================ 8. FORM ============================================================ */ .contact-form { display: flex; flex-direction: column; gap: .5rem; max-width: 520px; } .contact-form label { font-weight: 600; font-size: .9rem; margin-top: .5rem; } .contact-form input, .contact-form textarea { padding: .7rem .9rem; border: 1px solid var(--border); border-radius: 8px; font-family: inherit; font-size: 1rem; background: var(--surface); color: var(--ink); transition: border-color .15s, box-shadow .15s; } .contact-form input:focus, .contact-form textarea:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(46,111,242,.2); } .contact-form button { align-self: flex-start; margin-top: 1rem; } /* ============================================================ 9. FOOTER ============================================================ */ .site-footer { text-align: center; padding: 2rem 1.5rem; color: var(--ink-soft); font-size: .85rem; border-top: 1px solid var(--border); } /* ============================================================ 10. RESPONSIVE ============================================================ */ @media (min-width: 768px) { .hero h1 { font-size: 3.5rem; } main section { padding: 4rem 2rem; } } /* ============================================================ 11. ACCESSIBILITÀ ============================================================ */ :focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; } @media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
- Animazione ingresso card con
animation-delayprogressivo - Menu mobile con hamburger
- Barra progresso scroll con
position: fixed - Tema salvato in
localStorage - Sezione Skills con barre animate