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;
  }
}

Il tipo di media screen è il più usato. Altri: print(stampa), all (tutti i dispositivi — default se omesso).

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;
  }
}

/* Puntatore: distingue touch da mouse */
@media (hover: hover) {
  .card:hover { transform: translateY(-4px); }
}

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

Rispettare prefers-reduced-motion non è opzionale — è un requisito di accessibilità. Utenti con epilessia fotosensibile o disturbi vestibolari possono essere danneggiati da animazioni eccessive.

Editor Interattivo

Le card passano da 1 a 2 a 4 colonne al variare della larghezza della preview. Prova a modificare i valori di breakpoint o ad aggiungere nuove media query.

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.