03Lezione

Media Queries

Adattare il layout a diverse dimensioni di schermo, orientamento e preferenze utente. Il cuore del design responsive.

Introduzione

Le media query permettono di applicare stili CSS diversi a seconda del contesto: dimensione dello schermo, orientamento, risoluzione, preferenze di sistema. Sono la base tecnica del responsive design.

Una media query è una condizione: se vera, gli stili al suo interno vengono applicati. Se falsa, vengono completamente ignorati.

Il principio

Le media query non cambiano il markup HTML — cambiano solo i CSS applicati. Lo stesso HTML funziona su tutti i dispositivi: i CSS lo presentano in modo diverso.

Sintassi Base

La sintassi usa la keyword @media, seguita dal tipo di media e dalle condizioni tra parentesi.

css
/* Schermi più larghi di 768px */
@media screen and (min-width: 768px) {
  .container {
    max-width: 960px;
    margin: 0 auto;
  }
}

/* Stili per la stampa */
@media print {
  .navbar,
  .sidebar {
    display: none;
  }
}

La parola chiave dopo @media indica il tipo di dispositivo. Se omessa, vale all.

css
@media all    { }   /* tutti i dispositivi — default se omesso */
@media screen { }   /* schermi (il più usato) */
@media print  { }   /* stampa */
@media speech { }   /* sintetizzatori vocali */

Breakpoint Comuni

I breakpoint sono le larghezze a cui il layout cambia aspetto. Non esistono valori universali, ma questi sono i più usati nell'industria.

BreakpointLarghezzaDispositivo tipico
Mobile< 640pxSmartphone
Tablet≥ 640pxTablet verticale, smartphone grande
Laptop≥ 768pxTablet orizzontale, laptop piccolo
Desktop≥ 1024pxLaptop, desktop standard
Wide≥ 1280pxMonitor grande
css
/* Sistema di breakpoint mobile-first */
.element { font-size: 1rem; }           /* mobile (default) */

@media (min-width: 640px) {
  .element { font-size: 1.0625rem; }    /* tablet */
}

@media (min-width: 1024px) {
  .element { font-size: 1.125rem; }     /* desktop */
}

@media (min-width: 1280px) {
  .element { font-size: 1.25rem; }      /* wide */
}
Trova i breakpoint naturali

I breakpoint migliori si trovano guardando quando il layout si rompe, non scegliendo valori a caso. Parti mobile, allarga il browser, e aggiungi un breakpoint quando il design comincia a sembrare strano.

min-width vs max-width

min-width: gli stili si applicano da quella larghezza in su → approccio mobile-first. max-width: gli stili si applicanofino a quella larghezza → approccio desktop-first.

❌ Desktop-First
css
/* parte dal desktop, poi sovrascrive */
.card-grid {
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 1024px) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .card-grid {
    grid-template-columns: 1fr;
  }
}
✅ Mobile-First
css
/* parte dal mobile, poi espande */
.card-grid {
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

Combinare Condizioni

Le media query possono combinare più condizioni: and (tutte vere), la virgola , (almeno una vera — equivale a OR), e not (negazione).

css
/* AND: entrambe le condizioni devono essere vere */
@media (min-width: 640px) and (max-width: 1024px) {
  /* solo per tablet */
}

/* AND: schermo e orientamento landscape */
@media screen and (orientation: landscape) {
  /* solo in modalità orizzontale */
}

/* OR: almeno una condizione vera */
@media (max-width: 480px), (orientation: portrait) {
  /* mobile o portrait */
}

/* NOT: nega la condizione */
@media not (min-width: 768px) {
  /* equivale a max-width: 767px */
}

Media Features Avanzate

Oltre a width, le media query supportano molte altre caratteristiche del dispositivo e preferenze di sistema.

css
/* Orientamento del dispositivo */
@media (orientation: portrait)  { /* verticale */ }
@media (orientation: landscape) { /* orizzontale */ }

/* Preferenza tema di sistema */
@media (prefers-color-scheme: dark) {
  body { background: #0f172a; color: #f1f5f9; }
}

/* Animazioni ridotte (accessibilità) */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* Hover: il dispositivo supporta il passaggio del cursore?   */
/* valori: hover | none                                        */
@media (hover: hover) {
  .card:hover { transform: translateY(-4px); }
}

/* Precisione del puntatore                                    */
/* valori: fine (mouse) | coarse (touch) | none                */
@media (pointer: coarse) {
  .btn { min-height: 44px; min-width: 44px; } /* area tap più grande */
}

/* Display ad alta risoluzione / retina */
@media (min-resolution: 2dppx) {
  .logo { background-image: url('logo@2x.png'); }
}
prefers-reduced-motion è altamente consigliato

Rispettare prefers-reduced-motion è una buona pratica di accessibilità. Utenti con epilessia fotosensibile o disturbi vestibolari possono essere disturbati da animazioni eccessive — gestirla costa poco e migliora l'esperienza per tutti.

Riferimento Features

Tutte le media features più utili, organizzate per categoria.

Dimensioni viewport

css
@media (width: 800px) { }
@media (min-width: 480px) { }
@media (max-width: 1200px) { }
@media (height: 600px) { }
@media (min-height: 400px) { }
@media (max-height: 900px) { }

Display e risoluzione

css
@media (resolution: 96dpi) { }
@media (min-resolution: 2dppx) { }     /* retina */
@media (orientation: landscape) { }
@media (orientation: portrait) { }
@media (aspect-ratio: 16/9) { }
@media (min-aspect-ratio: 4/3) { }

Preferenze utente

css
@media (prefers-color-scheme: dark) { }
@media (prefers-color-scheme: light) { }
@media (prefers-reduced-motion: reduce) { }
@media (prefers-reduced-motion: no-preference) { }
@media (prefers-contrast: more) { }
@media (prefers-contrast: less) { }
@media (prefers-reduced-transparency: reduce) { }
@media (forced-colors: active) { }     /* Windows High Contrast */

Input e interazione

css
@media (hover: hover) { }       /* dispositivo ha hover (mouse) */
@media (hover: none) { }        /* touch, nessun hover */
@media (pointer: fine) { }      /* mouse, puntatore preciso */
@media (pointer: coarse) { }    /* touch, puntatore grossolano */
@media (pointer: none) { }      /* nessun puntatore */
@media (any-hover: hover) { }   /* almeno un input con hover */
@media (any-pointer: fine) { }  /* almeno un input preciso */

Esercizi

✏️Metti in pratica

Esercizio A — Base

Navigazione Responsive

Crea una navbar che mostra i link in riga su desktop e nasconde tutto tranne il logo su mobile. Usa display: none e @media (min-width: 768px).

Esercizio B — Intermedio

Card Grid con Tipografia Responsive

Griglia di card: 1 colonna su mobile, 2 su tablet (≥ 640px), 3 su desktop (≥ 1024px). Aggiungi anche tipografia responsive: font più grande su schermi grandi.

Esercizio C — Avanzato

Dark Mode Automatica + Motion Safe

Implementa dark mode automatica con prefers-color-scheme: darke disabilita tutte le transizioni con prefers-reduced-motion: reduce. Testa nelle impostazioni di sistema del tuo OS.