Passa al contenuto principale

CSS Real World Vademecum

1. Importazione font esterni

Cosa fa: Importa font professionali gratis da Google nel tuo sito.

<!-- Font singolo -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700,800" rel="stylesheet">

<!-- Font multipli -->
<link href="https://fonts.googleapis.com/css?family=Anton%7CBaskervville%7CRaleway&display=swap" rel="stylesheet">

I numeri (400,700,800) significano:

400 = normale
700 = grassetto (bold)
800 = extra grassetto

Poi nel CSS:

body {
font-family: 'Open Sans', Arial, sans-serif;
}

Analogia: È come ordinare penne speciali su Amazon invece di usare solo quelle del supermercato. Arrivano via internet e le usi quando vuoi!

Cosa fa: Importa migliaia di icone professionali

Nel <head>:

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">

Uso nel HTML:

<i class="fab fa-facebook-f"></i>  <!-- Facebook -->
<i class="fab fa-twitter"></i> <!-- Twitter -->
<i class="fas fa-heart"></i> <!-- Cuore -->

Classi Font Awesome:

  • fab = Font Awesome Brands (loghi aziende)
  • fas = Font Awesome Solid (icone piene)
  • far = Font Awesome Regular (icone vuote)




2. Selettori fondamentali

Selettore universale *

Cosa fa: Seleziona TUTTI gli elementi della pagina. Proprio tutti!

* {
box-sizing: border-box;
margin: 0;
padding: 0;
}

Reset universale completo

Cosa fa: Resetta TUTTO inclusi pseudo-elementi

*,
*::before,
*::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}

Analogia: Come dire "TUTTI in classe, compresi quelli in corridoio e in bagno, sedetevi!"

Selettore di tipo (tag)

Cosa fa: Seleziona tutti gli elementi di quel tipo HTML.

/* Tutti i paragrafi */
p {
line-height: 1.6;
margin-bottom: 1rem;
}

/* Specializzazioni */
p.warning { color: red; } /* Solo p con classe warning */
p[lang="en"] { font-style: italic; } /* Solo p in inglese */

Selettore di classe .class

Cosa fa: Seleziona elementi con quella classe, indipendentemente dal tag.

.importante {
background: yellow;
font-weight: bold;
}

Selettori multipli (senza spazio)

Cosa fa: Seleziona elementi che hanno TUTTE le classi specificate.

/* Elemento con ENTRAMBE le classi */
.social-icons.active {
color: blue;
}

Selettori combinati (virgola)

Cosa fa: Applica lo stesso stile a più selettori

h1, h2, h3, h4, h5, h6 {
font-family: 'Raleway', sans-serif;
}

Pseudo-classi di stato

/* Mouse sopra */
button:hover {
background: #f0f0f0;
cursor: pointer;
transform: translateY(-2px);
}

/* Mentre clicchi */
button:active {
transform: scale(0.95);
}

/* Link già visitato */
a:visited {
color: purple;
}

/* Elemento con focus (keyboard) */
input:focus {
outline: 2px solid blue;
background: #f0f8ff;
}

:not() pseudo-classe

/* Tutti i p tranne quelli con classe .no-margin */
p:not(.no-margin) {
margin-bottom: 1rem;
}

Pseudo-selettori di tipo

/* Primo elemento del suo tipo */
.line:first-of-type {
margin-top: 0;
}

/* Il secondo, terzo, ecc */
.line:nth-of-type(2) { transform: rotate(60deg); }
.line:nth-of-type(3) { transform: rotate(120deg); }

/* Posizioni pari e dispari */
tr:nth-of-type(odd) { background: #f0f0f0; }
tr:nth-of-type(even) { background: white; }

Pseudo-elementi ::before e ::after

/* Content vuoto per forme/decorazioni */
.penguin-body::before {
content: ""; /* OBBLIGATORIO anche se vuoto! */
width: 50%;
height: 45%;
background-color: gray;
}

::first-letter pseudo-elemento

.first-paragraph::first-letter {
font-size: 6rem;
color: orangered;
float: left;
margin-right: 1rem;
}

::selection pseudo-elemento

Cosa fa: Stilizza il testo quando lo selezioni!

::selection {
background: gold;
color: black;
}

/* Per Firefox */
::-moz-selection {
background: gold;
color: black;
}

Risultato: Quando selezioni del testo diventa dorato invece che blu!

Analogia: Come un evidenziatore personalizzato - scegli tu il colore!

Pseudo-classi moderne

:is() - Evita ripetizioni

/* PRIMA (ripetitivo) */
article h1:hover,
article h2:hover,
article h3:hover {
color: blue;
}

/* DOPO (con :is) */
article :is(h1, h2, h3):hover {
color: blue;
}

Analogia: Come dire "chiunque di voi tre" invece di chiamare uno per uno!

:where() - Come :is() ma con specificità 0

/* Non aumenta la specificità */
:where(article, section) p {
margin: 1rem;
}

Quando usarlo: Quando vuoi stili facilmente sovrascrivibili

:has() - Il parent selector! 2023

/* Stile al div SE contiene un'immagine */
div:has(> img) {
border: 2px solid blue;
padding: 1rem;
}

/* Card che contiene un video */
.card:has(video) {
background: black;
}

/* Form con input invalido */
form:has(input:invalid) {
border: 2px solid red;
}

RIVOLUZIONARIO! Prima non potevi stilizzare un parent basandoti sui figli!

Analogia: Come dire "colora di rosso le scatole che contengono mele"!





3. Box Model & Spaziatura

margin

Cosa fa: Crea spazio FUORI dall'elemento.

Shorthand spiegato:

/* Un valore = tutti i lati */
margin: 20px;

/* Due valori = verticale | orizzontale */
margin: 10px 20px;

/* Tre valori = top | lati | bottom */
margin: 10px 20px 30px;

/* Quattro = senso orario */
margin: 5px 10px 15px 20px;

Centrare con auto:

.container {
width: 800px;
margin: 0 auto; /* Magia! Si centra da solo */
}

Margini negativi:

.hero-title {
margin-top: -20px; /* Si sposta SU di 20px */
}

padding

.button {
padding: 10px 20px; /* verticale | orizzontale */
}

.card {
padding: 2rem; /* Uguale su tutti i lati */
}

border

/* Solido classico */
.box {
border: 2px solid black;
}

/* Stili diversi */
border: 3px dotted red; /* • • • • */
border: 2px dashed blue; /* - - - - */
border: 4px double green; /* ══════ */

border-radius avanzato

/* Solo angoli specifici */
.key {
border-radius: 0 0 3px 3px;
/* Squadrato sopra, arrotondato sotto */
}

box-sizing

/* Pattern di reset con inherit */
html {
box-sizing: border-box;
}

*, *::before, *::after {
box-sizing: inherit;
}

Dimensioni & unità

/* ASSOLUTE */
width: 200px; /* Pixel */

/* RELATIVE */
width: 80%; /* % del genitore */
font-size: 2rem; /* 2x root */
height: 50vh; /* 50% altezza viewport */
width: 55vw; /* 55% larghezza viewport */

Funzioni per dimensioni

calc() per calcoli

/* Larghezza totale meno margini fissi */
.container {
width: calc(100% - 40px);
}

/* Calcoli complessi */
.column {
width: calc((100% - 20px * 2) / 3);
}

min() e max()

Cosa fanno: Scelgono il valore minimo o massimo tra opzioni

/* min() - prende il PIÙ PICCOLO */
.sidebar {
width: min(300px, 100%);
/* Se lo schermo è < 300px, usa 100% */
}

/* max() - prende il PIÙ GRANDE */
.hero {
height: max(400px, 50vh);
/* Mai meno di 400px di altezza */
}

Analogia:

  • min() = "Dammi il bicchiere più piccolo tra questi"
  • max() = "Dammi il bicchiere più grande tra questi"

clamp() - Il limitatore intelligente

Cosa fa: Imposta un valore con limiti minimo e massimo

/* clamp(MIN, PREFERITO, MAX) */
.title {
font-size: clamp(1.5rem, 4vw, 3rem);
/* Mai < 1.5rem, idealmente 4vw, mai > 3rem */
}

.container {
width: clamp(300px, 80%, 1200px);
}

.padding-responsive {
padding: clamp(1rem, 5vw, 3rem);
}

Come funziona:

Mobile (400px screen):
4vw = 16px, ma minimo è 1.5rem (24px)
Risultato: 24px ✓

Desktop (1200px screen):
4vw = 48px, ma massimo è 3rem (48px)
Risultato: 48px ✓

Tablet (800px screen):
4vw = 32px (tra min e max)
Risultato: 32px ✓

Analogia: Come un termostato! Mantiene la temperatura (dimensione) sempre tra un minimo e un massimo, cercando di stare al valore ideale!





4. Tipografia

font-family

/* Con font Google */
h1 {
font-family: 'Anton', sans-serif;
}

/* Font multipli con fallback */
body {
font-family: 'Baskervville', Georgia, serif;
}

font-size con il trucco del 62.5%

html {
font-size: 62.5%; /* Ora 1rem = 10px invece di 16px! */
}

/* Ora i calcoli sono facilissimi! */
h1 { font-size: 3.2rem; } /* = 32px */
h2 { font-size: 2.4rem; } /* = 24px */
p { font-size: 1.6rem; } /* = 16px */

Font shorthand

/* Sintassi: style weight size/line-height family */
.title {
font: italic 700 2.4rem/1.2 'Raleway', sans-serif;
}

letter-spacing

h1 {
letter-spacing: 0.6px; /* Poco spazio */
}

.logo {
letter-spacing: 8px; /* M O L T O S P A Z I O */
}

line-height

p {
line-height: 1.6; /* 1.6 volte la font-size */
}

text-overflow - Testo troppo lungo

Cosa fa: Gestisce il testo che esce dal contenitore

.title {
white-space: nowrap; /* Non andare a capo */
overflow: hidden; /* Nascondi l'eccesso */
text-overflow: ellipsis; /* Aggiungi ... */
width: 200px;
}

Risultato:

"Questo è un titolo molto lungo" → "Questo è un titolo..."

Analogia: Come quando WhatsApp taglia i messaggi lunghi nelle notifiche!

Altri stili tipografici

/* text-decoration */
a {
text-decoration: none; /* Toglie sottolineatura */
}

/* white-space */
.nowrap {
white-space: nowrap; /* Non va mai a capo */
}

/* column-width - testo multi-colonna */
.article {
column-width: 25rem; /* Colonne larghe 25rem */
column-gap: 3rem; /* Spazio tra colonne */
}

/* Liste personalizzate */
.lists {
list-style-type: none; /* Rimuove i pallini */
list-style-position: inside; /* Pallini dentro il box */
}




5. Colori & Sfondi

color

/* Nome */
color: red;
color: orangered;

/* HEX */
color: #00beef;

/* RGB/RGBA */
color: rgb(255, 0, 0); /* Rosso */
color: rgba(255, 255, 255, 0.5); /* Bianco 50% trasparente */

background-color

.warning {
background-color: #fff3cd;
}

/* Con trasparenza */
.overlay {
background-color: rgba(0, 0, 0, 0.7);
}

Background avanzati

Proprietà di controllo sfondo

.hero {
background-image: url("hero.jpg");
background-size: cover; /* Copre tutto */
background-position: center; /* Centra */
background-repeat: no-repeat; /* Non ripetere */
background-attachment: fixed; /* Parallax! */
}

linear-gradient() con angoli

/* 45 gradi - diagonale */
background: linear-gradient(45deg, rgb(118, 201, 255), rgb(247, 255, 222));

/* Multi colore con stop percentuali */
background: linear-gradient(
45deg,
red 0%,
yellow 50%,
green 100%
);

radial-gradient()

Cosa fa: Crea sfumature circolari dal centro verso l'esterno

/* Sfumatura circolare base */
.circle {
background: radial-gradient(circle, yellow, orange, red);
}

/* Con posizione specifica */
.sun {
background: radial-gradient(
circle at top right,
yellow 0%,
orange 30%,
transparent 50%
);
}

/* Ellittica */
.ellipse {
background: radial-gradient(
ellipse at center,
white 0%,
black 100%
);
}

Visual:

radial-gradient:
⚪ (centro chiaro)
🟡
🟠
🔴 (bordi scuri)

conic-gradient()

Cosa fa: Sfumatura conica (tipo torta a colori!)

/* Arcobaleno circolare */
.rainbow-wheel {
background: conic-gradient(
red, yellow, green, cyan, blue, magenta, red
);
border-radius: 50%;
}

/* Grafico a torta */
.pie-chart {
background: conic-gradient(
red 0deg 90deg, /* 25% */
blue 90deg 180deg, /* 25% */
green 180deg 360deg /* 50% */
);
}

opacity

.faded {
opacity: 0.5; /* 50% trasparente TUTTO l'elemento */
}




6. Layout & Display

display

/* Block - nuovo "paragrafo" */
display: block;

/* Inline - nella riga */
display: inline;

/* Inline-block - ibrido */
display: inline-block;

/* Flex - contenitore flessibile */
display: flex;

/* Grid - griglia */
display: grid;

/* None - sparisce! */
display: none;

position

/* Static (default) */
position: static;

/* Relative - spostato dalla posizione normale */
position: relative;
top: 10px;
left: 20px;

/* Absolute - fuori dal flusso */
position: absolute;
top: 50%;
left: 50%;

/* Fixed - fisso nella viewport */
position: fixed;
bottom: 0;

/* Sticky - ibrido relative/fixed */
position: sticky;
top: 0;

z-index

.front { z-index: 100; }
.middle { z-index: 10; }
.behind { z-index: -1; }

float e clearfix

/* Float */
float: left;
float: right;
float: none;

/* Clearfix con overflow */
.container {
overflow: hidden; /* Contiene i float! */
}

aspect-ratio

Cosa fa: Mantiene le proporzioni di un elemento

/* Video 16:9 */
.video-container {
width: 100%;
aspect-ratio: 16 / 9;
background: black;
}

/* Quadrato perfetto */
.square {
width: 200px;
aspect-ratio: 1; /* o 1/1 */
}

/* Card con ratio custom */
.card {
width: 300px;
aspect-ratio: 3 / 4;
}

Prima di aspect-ratio (il vecchio trucco):

/* Il vecchio modo con padding */
.video-old {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
}

Analogia: Come dire "questa foto deve sempre essere rettangolare come una TV, non importa quanto la ridimensioni"!

Flexbox

Cosa fa: Crea layout flessibili in una direzione (riga o colonna).

Setup del container

.container {
display: flex; /* Attiva flex */
flex-direction: row; /* → orizzontale (default) */
flex-wrap: wrap; /* A capo se non c'è spazio */
gap: 1rem; /* Spazio tra elementi */
}

Proprietà del container complete

/* DIREZIONE */
flex-direction: row; /* → */
flex-direction: column; /* ↓ */
flex-direction: row-reverse; /* ← */
flex-direction: column-reverse; /* ↑ */

/* A CAPO */
flex-wrap: nowrap; /* Stringe tutto (default) */
flex-wrap: wrap; /* Va a capo */
flex-wrap: wrap-reverse; /* A capo al contrario */

/* ALLINEAMENTO ASSE PRINCIPALE */
justify-content: flex-start; /* |■■■ | */
justify-content: center; /* | ■■■ | */
justify-content: flex-end; /* | ■■■| */
justify-content: space-between;/* |■ ■ ■| */
justify-content: space-around; /* | ■ ■ ■ | */
justify-content: space-evenly; /* | ■ ■ ■ | */

/* ALLINEAMENTO ASSE TRASVERSALE */
align-items: stretch; /* Default - riempie */
align-items: center; /* Centra verticalmente */
align-items: flex-start; /* In alto */
align-items: flex-end; /* In basso */
align-items: baseline; /* Allinea le baseline del testo */

/* ALLINEAMENTO RIGHE (con wrap) */
align-content: flex-start;
align-content: center;
align-content: space-between;

Proprietà dei figli (flex items)

.item {
/* Crescita */
flex-grow: 1; /* Può crescere */

/* Riduzione */
flex-shrink: 0; /* Non può ridursi */

/* Dimensione base */
flex-basis: 200px; /* Dimensione iniziale */

/* Shorthand */
flex: 1 0 200px; /* grow shrink basis */

/* Auto-allineamento */
align-self: center; /* Override align-items */

/* Ordine */
order: -1; /* Viene prima (default: 0) */
}

Centratura perfetta 2D:

.center-perfect {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}

Grid - Layout a griglia completo

Grid base con tutte le proprietà

.grid-container {
display: grid;

/* Definizione colonne */
grid-template-columns: 200px 1fr 200px;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

/* Definizione righe */
grid-template-rows: 100px auto 100px;

/* Spazi */
gap: 20px; /* Entrambi */
row-gap: 30px; /* Solo righe */
column-gap: 20px; /* Solo colonne */

/* Allineamento */
justify-items: center; /* Orizzontale items */
align-items: center; /* Verticale items */
justify-content: center; /* Orizzontale griglia */
align-content: center; /* Verticale griglia */

/* Shorthand allineamento */
place-items: center; /* align + justify items */
place-content: center; /* align + justify content */
}

repeat() con auto-fit/auto-fill

/* auto-fit - stretcha le colonne */
.gallery {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

/* auto-fill - mantiene la dimensione */
.gallery {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

Differenza visual:

Container 800px, items 200px:

auto-fill: [200px][200px][200px][vuoto]
auto-fit: [266px][266px][266px] (stretchati)

grid-auto-flow

.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-auto-flow: column; /* Nuove colonne invece di righe */
grid-auto-flow: dense; /* Riempie i buchi */
grid-auto-columns: 1fr; /* Dimensione colonne auto */
}

Posizionamento avanzato

.item {
/* Colonne */
grid-column: 1 / 3; /* Da linea 1 a 3 */
grid-column: 1 / -1; /* Tutta la larghezza */
grid-column: span 2; /* Occupa 2 colonne */

/* Righe */
grid-row: 1 / 3;

/* Area nominata */
grid-area: header; /* Se usi grid-template-areas */
}

/* Grid template areas */
.layout {
display: grid;
grid-template-areas:
"header header header"
"sidebar content content"
"footer footer footer";
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }




7. CSS Custom Properties (Variabili)

Definizione e uso completo

:root {
/* Colori */
--primary: #007bff;
--primary-dark: #0056b3;
--primary-light: #e7f3ff;

/* Spacing sistema 8px */
--space-xs: 0.5rem; /* 8px */
--space-sm: 1rem; /* 16px */
--space-md: 2rem; /* 32px */
--space-lg: 3rem; /* 48px */
--space-xl: 4rem; /* 64px */

/* Typography */
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-mono: "Fira Code", "Courier New", monospace;

/* Shadows */
--shadow-sm: 0 1px 2px rgba(0,0,0,0.1);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);

/* Animations */
--transition-fast: 150ms ease;
--transition-base: 250ms ease;
--transition-slow: 350ms ease;

/* Breakpoints come custom properties */
--screen-sm: 640px;
--screen-md: 768px;
--screen-lg: 1024px;
}

Uso avanzato con fallback

.card {
/* var() con fallback */
background: var(--card-bg, white);
padding: var(--card-padding, 1rem);

/* Calcoli con variabili */
margin: calc(var(--space-md) * 2);

/* Variabili in media queries */
max-width: var(--container-width, 1200px);
}

/* Override locale */
.dark-theme {
--primary: #6c757d;
--card-bg: #2d2d2d;
}

Variabili dinamiche con JavaScript

.dynamic {
transform: translateX(var(--mouse-x));
transform: translateY(var(--mouse-y));
}
// JavaScript
element.style.setProperty('--mouse-x', `${x}px`);
element.style.setProperty('--mouse-y', `${y}px`);




8. Trasformazioni complete

Transform 2D

/* Rotazione */
transform: rotate(45deg);
transform: rotate(-180deg);
transform: rotate(0.5turn); /* Mezza rotazione */

/* Scala */
transform: scale(1.5); /* 150% */
transform: scale(0.5, 2); /* X: 50%, Y: 200% */
transform: scaleX(-1); /* Specchia orizzontalmente */
transform: scaleY(0.5); /* Schiaccia verticalmente */

/* Traslazione */
transform: translate(50px, 100px);
transform: translateX(-50%);
transform: translateY(2rem);

/* Skew (inclinazione) */
transform: skew(20deg, 10deg);
transform: skewX(20deg);
transform: skewY(-15deg);

/* Multiple transforms */
transform: rotate(45deg) scale(1.2) translateX(50px);

Transform 3D

/* Rotazione 3D */
.card {
transform: rotateX(180deg); /* Flip orizzontale */
transform: rotateY(180deg); /* Flip verticale */
transform: rotateZ(45deg); /* Come rotate normale */
transform: rotate3d(1, 1, 0, 45deg); /* Su asse custom */
}

/* Prospettiva */
.container {
perspective: 1000px; /* Punto di vista */
}

.card {
transform-style: preserve-3d; /* Mantieni 3D per i figli */
transform: translateZ(100px); /* Verso di te */
}

/* Card flip completo */
.flip-card {
width: 200px;
height: 300px;
perspective: 1000px;
}

.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
}

.flip-card:hover .flip-card-inner {
transform: rotateY(180deg);
}

.flip-card-front, .flip-card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}

.flip-card-back {
transform: rotateY(180deg);
}

transform-origin completo

/* Keywords */
transform-origin: center; /* Default */
transform-origin: top left;
transform-origin: bottom right;

/* Percentuali */
transform-origin: 0% 0%; /* Top left */
transform-origin: 100% 100%; /* Bottom right */

/* Valori misti */
transform-origin: left 50%;
transform-origin: 10px 20px;

/* 3D */
transform-origin: center center -50px;




9. Animazioni complete

@keyframes avanzati

/* Multi-step animation */
@keyframes bounce {
0%, 100% {
transform: translateY(0);
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
}
50% {
transform: translateY(-25%);
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
}

/* Animazione complessa */
@keyframes morphing {
0% {
border-radius: 50%;
transform: rotate(0deg);
background: red;
}
33% {
border-radius: 0%;
transform: rotate(120deg) scale(0.5);
background: blue;
}
66% {
border-radius: 50% 0;
transform: rotate(240deg) scale(1.5);
background: green;
}
100% {
border-radius: 50%;
transform: rotate(360deg);
background: red;
}
}

Proprietà animazione complete

.animated {
/* Proprietà singole */
animation-name: bounce;
animation-duration: 2s;
animation-timing-function: ease-in-out;
animation-delay: 0.5s;
animation-iteration-count: 3; /* o infinite */
animation-direction: alternate; /* o reverse, alternate-reverse */
animation-fill-mode: both; /* o forwards, backwards */
animation-play-state: running; /* o paused */

/* Shorthand completa */
animation: bounce 2s ease-in-out 0.5s 3 alternate both;

/* Multiple animations */
animation:
bounce 2s infinite,
fade 1s ease-out,
rotate 3s linear infinite;
}

Animation timing functions complete

/* Predefinite */
animation-timing-function: linear;
animation-timing-function: ease;
animation-timing-function: ease-in;
animation-timing-function: ease-out;
animation-timing-function: ease-in-out;

/* Steps (per sprite animations) */
animation-timing-function: steps(12);
animation-timing-function: steps(12, start);
animation-timing-function: steps(12, end);

/* Cubic bezier personalizzati */
animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* Bounce */
animation-timing-function: cubic-bezier(0.87, 0, 0.24, 0.99); /* Dramatic */




10. Transizioni

Sintassi

.element {
/* Proprietà singole */
transition-property: all; /* o specifiche: transform, opacity */
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;

/* Shorthand (ordine: property duration timing-function delay) */
transition: all 0.3s ease 0s;

/* Multiple transitions */
transition:
transform 0.3s ease,
opacity 0.2s ease 0.1s, /* con delay */
background-color 0.5s linear;
}

Dove metterla (regola d’oro)

/* ❌ Transizione SOLO su :hover → al “mouse out” non anima come ti aspetti */
.button:hover {
transition: transform 0.2s ease;
transform: translateY(-2px);
}

/* ✅ Transizione sullo stato base → anima sia entrando che uscendo */
.button {
transition: transform 0.2s ease;
}
.button:hover {
transform: translateY(-2px);
}

Evita all (specifica cosa vuoi animare)

/* ❌ */
.card { transition: all 0.3s ease; }

/* ✅ */
.card {
transition:
transform 0.25s ease,
opacity 0.2s ease,
background-color 0.3s linear;
}

Proprietà “consigliate” (fluide)

/* ✅ In genere più fluide e prevedibili */
.modal {
transition: transform 0.25s ease, opacity 0.2s ease;
transform: translateY(8px);
opacity: 0;
}
.modal.is-open {
transform: translateY(0);
opacity: 1;
}

Proprietà “costose” (da usare con cautela)

/* ⚠️ Spesso più pesanti perché impattano layout/paint */
.panel {
transition: width 0.3s ease, height 0.3s ease, top 0.3s ease, left 0.3s ease;
}

/* ✅ Alternative tipiche */
.panel {
transition: transform 0.3s ease;
}
.panel.is-open {
transform: scaleY(1);
}
.panel {
transform: scaleY(0);
transform-origin: top;
}

Easing (timing-function) più usati

.element {
transition-timing-function: ease; /* default “ok” */
/* transition-timing-function: linear; costante */
/* transition-timing-function: ease-in; parte lento */
/* transition-timing-function: ease-out; arriva lento */
/* transition-timing-function: ease-in-out; morbido */
}

/* ✅ Custom */
.element {
transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1);
}

Ritardi (delay) intelligenti

/* ✅ Delay solo in entrata */
.toast {
transition: opacity 0.2s ease 0s, transform 0.2s ease 0s;
opacity: 0;
transform: translateY(6px);
}
.toast.is-open {
transition-delay: 0.1s; /* entra dopo */
opacity: 1;
transform: translateY(0);
}

/* ✅ Delay diverso per proprietà diverse */
.toast {
transition:
opacity 0.2s ease 0s,
transform 0.2s ease 0s;
}
.toast.is-open {
transition:
opacity 0.2s ease 0.05s,
transform 0.2s ease 0s;
}

“Mostra/Nascondi” senza display (che non si anima)

/* ❌ display non è animabile */
/* .dropdown { display: none; } .dropdown.open { display: block; } */

/* ✅ Opacity + visibility + pointer-events */
.dropdown {
opacity: 0;
visibility: hidden;
pointer-events: none;
transform: translateY(6px);

transition:
opacity 0.15s ease,
transform 0.15s ease,
visibility 0s linear 0.15s; /* aspetta la fine prima di nascondere */
}

.dropdown.open {
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: translateY(0);

transition:
opacity 0.15s ease,
transform 0.15s ease,
visibility 0s; /* subito visibile */
}

Accessibilità: rispetta “reduced motion”

/* ✅ Riduci o elimina transizioni per chi lo richiede */
@media (prefers-reduced-motion: reduce) {
* {
transition: none !important;
scroll-behavior: auto !important;
}
}

Stati interattivi completi (hover + focus-visible)

.button {
transition: transform 0.15s ease, box-shadow 0.2s ease, background-color 0.2s ease;
}

.button:hover {
transform: translateY(-1px);
}

.button:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}




11. Filtri ed Effetti

filter completo

/* Singoli filtri */
.image {
filter: blur(5px);
filter: brightness(1.5); /* 150% */
filter: contrast(2); /* 200% */
filter: grayscale(100%); /* B&W */
filter: hue-rotate(90deg); /* Ruota colori */
filter: invert(100%); /* Negativo */
filter: opacity(50%); /* Come opacity */
filter: saturate(2); /* 200% saturazione */
filter: sepia(100%); /* Effetto seppia */
filter: drop-shadow(5px 5px 10px rgba(0,0,0,0.5));

/* Filtri multipli */
filter: contrast(1.2) brightness(1.1) saturate(1.3);

/* Blur + grayscale per disabled state */
filter: blur(2px) grayscale(100%) opacity(0.7);
}

backdrop-filter - Effetto vetro!

/* Glassmorphism effect */
.glass {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}

/* Dark glass */
.dark-glass {
background: rgba(0, 0, 0, 0.3);
backdrop-filter: blur(20px) saturate(1.5);
}

/* Tutti i backdrop filters */
.effects {
backdrop-filter: blur(10px);
backdrop-filter: brightness(0.8);
backdrop-filter: contrast(1.2);
backdrop-filter: grayscale(50%);
backdrop-filter: blur(10px) brightness(0.8);
}

Nota: Non supportato in tutti i browser! Usa @supports:

@supports (backdrop-filter: blur(10px)) {
.glass {
backdrop-filter: blur(10px);
}
}

clip-path - Forme personalizzate

Cosa fa: Ritaglia l'elemento in forme custom!

/* Forme base */
.circle {
clip-path: circle(50%);
}

.ellipse {
clip-path: ellipse(130px 140px at 10% 20%);
}

/* Poligoni */
.triangle {
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.hexagon {
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}

.star {
clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}

/* Animare clip-path */
.morph {
clip-path: circle(50%);
transition: clip-path 0.5s ease;
}

.morph:hover {
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}

Visual:

Normale:    clip-path: circle(50%):    clip-path: triangle:
┌────────┐ ⭕ 🔺
│ │
│ IMG │ → IMG IMG
│ │
└────────┘ ⭕ 🔻

mix-blend-mode

Cosa fa: Mischia i colori come in Photoshop!

.overlay-text {
mix-blend-mode: multiply;
mix-blend-mode: screen;
mix-blend-mode: overlay;
mix-blend-mode: difference;
mix-blend-mode: color-dodge;
mix-blend-mode: color-burn;
}

/* Testo che si adatta allo sfondo */
.adaptive-text {
color: white;
mix-blend-mode: difference;
}




12. Controlli utente

cursor - Tutti i valori

cursor: pointer;        /* 👆 Manina */
cursor: grab; /* ✋ Mano aperta */
cursor: grabbing; /* ✊ Mano chiusa */
cursor: not-allowed; /* 🚫 Divieto */
cursor: wait; /* ⏳ Attesa */
cursor: help; /* ❓ Aiuto */
cursor: text; /* 📝 Testo */
cursor: crosshair; /* ✚ Mirino */
cursor: move; /* ✥ Movimento */
cursor: zoom-in; /* 🔍+ Zoom in */
cursor: zoom-out; /* 🔍- Zoom out */
cursor: progress; /* ⏳ In elaborazione */

/* Cursor personalizzato */
cursor: url('cursor.png'), auto;
cursor: url('cursor.svg') 4 12, auto; /* Con hotspot */

user-select - Controllo selezione

/* Non selezionabile */
.no-select {
user-select: none;
-webkit-user-select: none; /* Safari */
}

/* Seleziona tutto al click */
.select-all {
user-select: all;
}

/* Solo testo selezionabile */
.text-only {
user-select: text;
}

/* Auto (default) */
.normal {
user-select: auto;
}

Uso pratico:

/* Bottoni non selezionabili */
button {
user-select: none;
}

/* Codice che si seleziona tutto */
.code-snippet {
user-select: all;
}

pointer-events

Cosa fa: Controlla se un elemento può ricevere click

/* Non cliccabile */
.disabled {
pointer-events: none;
opacity: 0.5;
}

/* Click attraverso l'elemento */
.overlay {
pointer-events: none;
}

/* Solo alcuni eventi */
.special {
pointer-events: auto; /* Tutti (default) */
pointer-events: visiblePainted; /* Solo parti visibili */
}

Uso pratico: Overlay che non blocca i click!

.watermark {
position: fixed;
top: 0;
left: 0;
pointer-events: none; /* Click passano attraverso! */
opacity: 0.1;
}




13. Scroll avanzato

scroll-behavior

html {
scroll-behavior: smooth; /* Scroll animato */
scroll-behavior: auto; /* Scroll normale */
}

Scroll Snap - Scroll magnetico

Cosa fa: Fa "agganciare" lo scroll a punti specifici

/* Container */
.carousel {
scroll-snap-type: x mandatory; /* Asse X, obbligatorio */
overflow-x: scroll;
display: flex;
}

/* Items */
.slide {
scroll-snap-align: center; /* Si centra */
flex: 0 0 100%;
}

/* Vertical esempio */
.vertical-sections {
scroll-snap-type: y proximity; /* Asse Y, suggerito */
overflow-y: scroll;
height: 100vh;
}

.section {
scroll-snap-align: start; /* Si allinea all'inizio */
height: 100vh;
}

Opzioni scroll-snap-type:

  • x / y = asse
  • mandatory = sempre aggancia
  • proximity = aggancia se vicino

Opzioni scroll-snap-align:

  • start = inizio elemento
  • center = centro elemento
  • end = fine elemento

overscroll-behavior

Cosa fa: Controlla cosa succede quando scrolli oltre i limiti

/* Previene scroll del parent */
.modal {
overscroll-behavior: contain;
}

/* Disabilita pull-to-refresh */
body {
overscroll-behavior-y: none;
}

/* Default */
.normal {
overscroll-behavior: auto;
}




14. Responsive Design avanzato

Container Queries

Cosa sono: Media queries basate sul container, non sul viewport!

/* Definisci container */
.card-container {
container-type: inline-size;
container-name: card;
}

/* Query basate sul container */
@container card (min-width: 400px) {
.card {
display: flex;
gap: 2rem;
}
}

@container (min-width: 700px) {
.card {
grid-template-columns: 2fr 1fr;
}
}

Rivoluzionario! Componenti veramente responsive!

Funzioni responsive

/* clamp() per tipografia responsive */
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
}

/* min() per container */
.container {
width: min(90%, 1200px);
}

/* max() per minimi garantiti */
.card {
width: max(300px, 30%);
}




15. Performance

will-change

Cosa fa: Avvisa il browser di future animazioni per ottimizzare

.animated {
will-change: transform;
}

.multi {
will-change: transform, opacity;
}

/* Importante: rimuovi dopo l'animazione */
.finished {
will-change: auto;
}

Quando usarlo:

  • Prima di animazioni pesanti
  • Non su troppi elementi
  • Rimuovi quando finito

contain

Cosa fa: Isola parti della pagina per performance

.widget {
contain: layout; /* Layout isolato */
contain: paint; /* Paint isolato */
contain: size; /* Size isolato */
contain: style; /* Style isolato */

/* Combinati */
contain: layout paint;
contain: strict; /* Tutti */
}




16. Feature Detection

@supports

Cosa fa: Applica CSS solo se supportato

/* Se supporta grid */
@supports (display: grid) {
.container {
display: grid;
}
}

/* Se NON supporta */
@supports not (backdrop-filter: blur(10px)) {
.glass {
background: rgba(255,255,255,0.95);
}
}

/* Condizioni multiple */
@supports (display: grid) and (gap: 1rem) {
.modern-grid {
display: grid;
gap: 1rem;
}
}




17. CSS Counters — Numerazione automatica

/* Reset counter (parte da 0 → il primo increment lo porta a 1) */
.chapters {
counter-reset: chapter;
}

/* Incrementa e mostra */
.chapter::before {
counter-increment: chapter;
content: "Capitolo " counter(chapter) ": ";
}

/* Counter annidati */
.book {
counter-reset: chapter;
}

.chapter {
counter-reset: section; /* ogni nuovo capitolo azzera le sezioni */
counter-increment: chapter; /* aumenta il capitolo quando appare */
}

.section::before {
counter-increment: section; /* aumenta la sezione quando appare */
content: counter(chapter) "." counter(section) " ";
}

Come funziona (in 3 mosse)

/* 1) counter-reset: crea/azzera un contatore */
.wrapper { counter-reset: step; }

/* 2) counter-increment: lo aumenta quando l’elemento “passa” */
.item::before { counter-increment: step; }

/* 3) counter(): lo stampa dentro content */
.item::before { content: counter(step) ". "; }

Dove metterlo (regola pratica)

/* ✅ reset sul contenitore */
.list { counter-reset: item; }

/* ✅ increment sull’elemento che vuoi numerare */
.list > li::before {
counter-increment: item;
content: counter(item) ". ";
}

Cambiare stile di numerazione (decimal, roman, alpha…)

.list { counter-reset: item; }

.list > li::before {
counter-increment: item;

/* decimal | lower-roman | upper-roman | lower-alpha | upper-alpha */
content: counter(item, upper-roman) ". ";
}

Prefissi, parentesi, separatori (formattazione)

.steps { counter-reset: step; }

.step::before {
counter-increment: step;
content: "Step " counter(step) " → ";
}

Numerazione annidata (1, 1.1, 1.1.1) con counters()

/* ✅ counters(name, separator) stampa tutta la catena */
.toc {
counter-reset: h2;
}

.toc .h2 {
counter-reset: h3; /* ogni h2 azzera h3 */
}

.toc .h2::before {
counter-increment: h2;
content: counter(h2) " ";
}

.toc .h3::before {
counter-increment: h3;
content: counter(h2) "." counter(h3) " ";
}

/* Variante: se usi lo stesso counter-name su più livelli */
.outline { counter-reset: item; }

.outline li {
counter-increment: item;
}

.outline li::before {
content: counters(item, ".") " ";
}

Partire da un numero diverso

/* Parte da 4 perché resetta a 3 e poi increment → 4 */
.chapters { counter-reset: chapter 3; }

.chapter::before {
counter-increment: chapter;
content: "Capitolo " counter(chapter) ": ";
}

Reverse counting (contare al contrario)

/* ✅ decrementa invece di incrementare */
.countdown { counter-reset: n 5; }

.countdown .item::before {
counter-increment: n -1;
content: "T-" counter(n) " ";
}

Usare i counter con liste (quando NON vuoi <ol>)

/* ❌ se è una lista “vera”, meglio <ol> */
.fake-ol { counter-reset: item; }

.fake-ol > li::before {
counter-increment: item;
content: counter(item) ") ";
font-variant-numeric: tabular-nums;
}

Mostrare numeri “allineati bene”

.list { counter-reset: item; }

.list > li {
display: flex;
gap: 0.6rem;
}

.list > li::before {
counter-increment: item;
content: counter(item) ".";
min-width: 2ch; /* spazio fisso per 1..99 */
text-align: right;
font-variant-numeric: tabular-nums;
}

Counters e pseudo-elementi (limite importante)

/* ✅ i counter si stampano quasi sempre con ::before / ::after */
.item::before {
counter-increment: n;
content: counter(n);
}

/* ⚠️ senza content non “vedi” nulla */
.item::before {
counter-increment: n;
/* content: ...; ← se manca, il numero non appare */
}

Scope (dove “vive” un counter)

/* ✅ ogni contenitore con counter-reset crea una “nuova serie” */
.article { counter-reset: fig; }

.article figure::before {
counter-increment: fig;
content: "Figura " counter(fig) " — ";
}

Risultato:

Capitolo 1: Introduzione
1.1 Cos'è CSS
1.2 Come funziona
Capitolo 2: Avanzato
2.1 Flexbox
2.2 Grid




I 10 comandamenti del CSS

1. Niente !important — Se urli sempre, nessuno ti ascolta

Perché: !important rompe la cascata e rende il CSS difficile da mantenere. Se lo usi spesso, stai combattendo contro la tua stessa struttura.

/* ❌ */
.button { color: red !important; }

/* ✅ */
.button { color: red; }
.page .button { color: red; } /* se serve più contesto */

Analogia: è come parlare urlando in una stanza. Funziona… ma poi non riesci più a “parlare normale”.

Nota pro: !important può avere senso in utility CSS o override molto mirati, ma come eccezione, non come stile di vita.


2. Stila con le classi, non con gli ID — Gli ID sono “troppo potenti”

Perché: gli ID hanno specificità altissima e ti costringono a scrivere selettori sempre più complicati per sovrascriverli.

/* ❌ */
#cta { background: black; }

/* ✅ */
.cta { background: black; }

Analogia: un ID è un martello pneumatico. Per piantare un chiodo, basta un martello normale (le classi).


3. Selettori corti — Non scrivere “romanzi” per trovare un elemento

Perché: selettori lunghi e super specifici sono fragili: basta cambiare una div e si rompe tutto.

/* ❌ */
main .wrapper .content .card .title { font-weight: 700; }

/* ✅ */
.card__title { font-weight: 700; }

Analogia: è come dare indicazioni dicendo gira a destra al bar, poi a sinistra al tabaccaio, poi dopo il semaforo entra nel vicolo…”. Meglio un indirizzo chiaro.


4. Non usare CSS inline — Separazione dei compiti (di nuovo)

Perché: lo stile inline è difficile da riutilizzare e da mantenere. Il CSS deve vivere nel CSS.

<!-- ❌ -->
<p style="margin-top: 12px; color: #333;">Testo</p>

<!-- ✅ -->
<p class="text">Testo</p>
.text { margin-top: 12px; color: #333; }

Analogia: è come copiare-incollare la stessa frase in 30 punti: quando devi correggerla, impazzisci. Meglio una sola regola riutilizzabile.


5. Mobile-first — Parti piccolo, poi espandi

Perché: è più naturale costruire per schermi piccoli e poi aggiungere complessità per quelli grandi.

/* ✅ mobile default */
.card { padding: 12px; }

/* ✅ poi “upgrade” */
@media (min-width: 768px) {
.card { padding: 24px; }
}

Analogia: è come preparare uno zaino: metti l’essenziale (mobile), poi aggiungi il resto solo se hai spazio (desktop).


6. Usa unità relative — Il sito deve “respirare”

Perché: rem, %, vw, clamp() rendono tutto più adattabile. I pixel ovunque spesso creano layout rigidi.

/* ❌ */
h1 { font-size: 42px; }

/* ✅ */
h1 { font-size: clamp(1.8rem, 3vw, 2.6rem); }

Analogia: i pixel sono scarpe di una misura sola. Le unità relative sono scarpe regolabili.


7. Layout moderni — Flexbox e Grid, non “hack”

Perché: float e trucchi vari sono fragili. Flex e Grid sono fatti apposta per layout.

/* ❌ (vecchi compromessi) */
.col { float: left; width: 50%; }

/* ✅ Flex */
.row { display: flex; gap: 16px; }
.col { flex: 1; }

/* ✅ Grid */
.grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }

Analogia: non costruire una casa con lo scotch. Usa gli attrezzi giusti.


8. box-sizing: border-box — Misure che non mentono

Perché: con border-box padding e bordo sono inclusi nella larghezza. Eviti “perché sta sforando??”.

/* ✅ */
*,
*::before,
*::after {
box-sizing: border-box;
}

Analogia: è come avere un righello che misura sempre allo stesso modo, senza sorprese.


9. Variabili CSS — Non ripeterti come un pappagallo

Perché: colori e spaziature ripetute diventano un incubo. Le custom properties rendono tutto più consistente e tematizzabile.

/* ✅ */
:root {
--space-2: 8px;
--space-3: 12px;
--text: #222;
--brand: #2563eb;
}

.button {
padding: var(--space-2) var(--space-3);
color: white;
background: var(--brand);
}

Analogia: le variabili sono come una playlist: cambi una canzone e cambia tutta l’atmosfera.


10. Animazioni “furbe” — Muovi con transform, non con dolore

Perché: animare top/left/width/height può essere più pesante. transform e opacity di solito sono più fluidi.

/* ❌ */
.modal { position: relative; top: 0; transition: top .2s; }
.modal.open { top: 20px; }

/* ✅ */
.modal { transform: translateY(0); transition: transform .2s, opacity .2s; }
.modal.open { transform: translateY(20px); }

Analogia: è come spostare un mobile trascinandolo sul pavimento (fatica), rispetto a mettergli le ruote (scorre).


Bonus (super consigliati)

11. Focus visibile — Non togliere la bussola da tastiera

Perché: chi naviga con tastiera deve vedere dove si trova. Togliere l’outline senza alternativa è una trappola.

/* ❌ */
:focus { outline: none; }

/* ✅ */
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}

Analogia: è come spegnere i fari di notte. Tu magari vedi… altri no.


12. Rispetta “reduced motion” — Non tutti vogliono montagne russe

Perché: alcune persone soffrono animazioni eccessive. Con prefers-reduced-motion fai un gesto da pro.

@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
scroll-behavior: auto !important;
}
}

Analogia: è come abbassare il volume quando qualcuno ti dice “mi dà fastidio”.