Una media query in un esempio
Una media query racchiude il CSS in una condizione. Le regole dentro @media (min-width: 600px) si applicano solo mentre il viewport è largo almeno 600px:
L'anteprima è un frame, e una media query al suo interno misura il frame, non il tuo schermo. Su un desktop è larga più o meno quanto la colonna di questo articolo, di solito più di 600px, quindi il riquadro è blu. Restringi la finestra del browser finché il frame scende sotto i 600px e diventa ambra; la riga sotto il riquadro mostra dal vivo la larghezza del frame. Su un telefono il frame è già stretto, quindi vedi la versione ambra.
La sintassi di @media
@media (min-width: 600px) { ... } /* one condition */
@media (min-width: 600px) and (max-width: 899px) { ... } /* both must be true */
@media (max-width: 599px), print { ... } /* either one (comma = or) */
@media not print { ... } /* negation */
@media screen and (orientation: landscape) { ... } /* media type plus a feature */
@media (width >= 600px) { ... } /* range syntax */
@media (600px <= width < 900px) { ... } /* a range with both ends */
and vuole uno spazio su entrambi i lati: (min-width: 600px)and(max-width: 900px) non è valido e l'intera query viene ignorata. La sintassi a intervalli (width >= 600px) è supportata dalle versioni attuali di Chrome, Firefox e Safari e si legge meglio di min-width, soprattutto per "fino a, escluso".
Le caratteristiche che userai di più:
| Caratteristica | Corrisponde quando | Esempio |
|---|---|---|
min-width / width >= | il viewport è largo almeno così | (min-width: 768px) |
max-width / width <= | il viewport è largo al massimo così | (max-width: 767px) |
orientation | portrait (più alto che largo) o landscape | (orientation: landscape) |
hover | il puntatore principale può fare hover (hover) o no (none, la maggior parte degli schermi touch) | (hover: hover) |
pointer | il puntatore principale è fine (mouse) o coarse (dito) | (pointer: coarse) |
prefers-color-scheme | l'utente ha scelto un tema dark o light | (prefers-color-scheme: dark) |
prefers-reduced-motion | l'utente ha chiesto al sistema meno movimento | (prefers-reduced-motion: reduce) |
print (un tipo di media) | la pagina viene stampata o salvata come PDF | @media print |
Mobile first: breakpoint con min-width
Scrivi il layout per il telefono come CSS di base, poi aggiungi query min-width che cambiano il layout man mano che lo spazio cresce. Ogni query deve descrivere solo ciò che cambia:
In una finestra desktop larga l'anteprima supera i 720px, quindi vedi tre colonne; la riga sotto la griglia mostra la larghezza e il numero di colonne. Restringi la finestra e scende a due sotto i 720px e a una sotto i 480px. L'ordine delle due query conta: su uno schermo largo sono vere entrambe e vince quella scritta dopo, quindi le query min-width vanno dalla più piccola alla più grande. (Con le query max-width è il contrario: prima la più grande.)
Scegliere i breakpoint
Non esiste un elenco ufficiale. Questi sono valori comuni e ciò che di solito separano:
| Breakpoint | Di solito |
|---|---|
min-width: 640px | telefoni grandi in orizzontale, tablet piccoli |
min-width: 768px | tablet in verticale |
min-width: 1024px | tablet in orizzontale, portatili piccoli |
min-width: 1280px | desktop |
Un metodo migliore: parti dal layout stretto, allarga la finestra finché qualcosa non va (righe troppo lunghe, card troppo larghe) e metti lì un breakpoint. Due o tre breakpoint bastano per la maggior parte delle pagine. Spesso non ne serve nessuno: repeat(auto-fit, minmax(200px, 1fr)) in grid, flex-wrap e clamp() si adattano in modo continuo.
Ogni pagina ha bisogno del meta tag viewport
Senza questo tag nell'<head>, i browser dei telefoni impaginano la pagina come se lo schermo fosse largo circa 980px e poi la rimpiccioliscono, quindi la tua query min-width: 480px è sempre vera e il layout per telefono non si vede mai:
<meta name="viewport" content="width=device-width, initial-scale=1">
La pagina su meta viewport spiega ogni valore.
Tema scuro con prefers-color-scheme
prefers-color-scheme segue l'impostazione chiara o scura del sistema operativo. Il modo più pulito per usarla è tenere i colori in variabili CSS e cambiare solo le variabili dentro la query:
In questa anteprima la query può stampare false anche quando il tuo sistema è impostato sul tema scuro: Chrome non passa l'impostazione del sistema a un frame isolato come questo. Il pulsante imposta a mano le stesse variabili, ed è così che funziona il selettore del tema di un sito. :root[data-theme] è più specifico del semplice :root dentro la query, quindi la scelta di chi legge vince su quella del sistema. Salva l'esempio in un file e aprilo per vedere la query seguire il tuo sistema.
Lo script mostra la seconda metà delle media query: matchMedia() esegue la stessa query da JavaScript, restituisce se corrisponde in quel momento e lancia un evento change quando la risposta cambia. Usalo quando il comportamento (non solo lo stile) dipende dallo schermo, per esempio per aprire un menu in modo diverso sui dispositivi touch.
Il movimento funziona allo stesso modo. Racchiudi le animazioni grandi o in loop in un controllo su prefers-reduced-motion, come mostrato nella pagina sulle animazioni.
Container query: quando deve decidere il componente
Una media query conosce solo il viewport. Una card che nella stessa pagina sta sia in una colonna principale larga sia in una barra laterale stretta deve invece conoscere il proprio spazio. È questo che fa una container query: marca il genitore con container-type: inline-size, poi usa @container con le stesse condizioni.
Trascina l'angolo del riquadro grigio per ridimensionarlo. La card cambia layout a 360px di larghezza del riquadro, qualunque sia la dimensione della finestra:
Ai 480px iniziali l'immagine sta accanto al testo. Stringi il riquadro sotto i 376px (360px di contenuto più 8px di padding per lato) e l'immagine si sposta sopra il testo. Le container query funzionano in tutti i principali browser attuali.
Stili per la stampa
@media print si applica solo quando la pagina viene stampata o salvata come PDF. Nascondi navigazione e pulsanti, e usa testo scuro su bianco:
@media print {
nav, .ad, button { display: none; }
body { color: black; background: white; }
a::after { content: " (" attr(href) ")"; } /* print the URL after each link */
}
Errori comuni
- Nessun meta tag viewport. I telefoni riportano allora un viewport di layout largo e le query per schermi piccoli non corrispondono mai.
- Query nell'ordine sbagliato. Due query vere con lo stesso selettore: vince quella scritta dopo. Ordina le query
min-widthdalla più piccola alla più grande. - Confini che si sovrappongono o lasciano buchi.
max-width: 768pxemin-width: 768pxcorrispondono entrambe esattamente a 768px. Usa767pxper una delle due, oppure la sintassi a intervalli(width < 768px)e(width >= 768px). - Nessuno spazio dopo
and.and(non è valido e la query viene scartata in silenzio. - Testare solo ridimensionando una finestra desktop. Controlla anche su un telefono vero o con la modalità dispositivo del browser, che applica viewport, densità di pixel e touch del telefono.
- Troppi breakpoint. Se ogni componente ne vuole uno suo, prova invece grid con
auto-fit,flex-wrapo le container query.
Domande frequenti
Cos'è una media query in CSS?
Una regola che applica il CSS al suo interno solo quando è vera una condizione sul dispositivo o sulla finestra. @media (min-width: 600px) { ... } applica i suoi stili solo quando il viewport è largo almeno 600px, ed è così che una pagina si adatta dai telefoni ai desktop.
Meglio media query con min-width o con max-width?
La maggior parte dei siti si scrive mobile first: il CSS di base è per gli schermi piccoli e le query min-width aggiungono layout man mano che lo schermo cresce. Le query max-width funzionano al contrario, partendo dal layout desktop. Vanno bene entrambe; mescolarle sullo stesso elemento porta a sovrapposizioni e buchi ai confini.
Quali sono i breakpoint standard per le media query?
Non esiste uno standard ufficiale. Le scelte comuni sono intorno a 640px, 768px, 1024px e 1280px, ma la regola migliore è aggiungere un breakpoint dove il tuo layout comincia a non funzionare più, e tenere basso il numero di breakpoint.
Perché la mia media query non funziona sul telefono?
La causa più comune è un meta tag viewport mancante. Senza <meta name="viewport" content="width=device-width, initial-scale=1">, i browser mobile fanno finta che la pagina sia larga circa 980px, quindi le query per larghezze piccole non corrispondono mai. Controlla anche che la query venga dopo le regole che sovrascrive.
Come si scrive una media query per il tema scuro?
Usa @media (prefers-color-scheme: dark) { ... }. Corrisponde quando il sistema operativo o il browser dell'utente è impostato su un tema scuro, e al suo interno puoi sovrascrivere colori o variabili CSS.
Qual è la differenza tra media query e container query?
Una media query verifica il viewport (l'intera finestra). Una container query, scritta con @container, verifica la dimensione di un elemento genitore che marchi con container-type: inline-size. Usa le container query per un componente che compare sia in punti larghi sia in punti stretti della stessa pagina.