Une media query en un exemple
Une media query entoure du CSS d'une condition. Les règles à l'intérieur de @media (min-width: 600px) ne s'appliquent que tant que le viewport fait au moins 600px de large :
L'aperçu est un cadre, et une media query à l'intérieur mesure ce cadre, pas votre écran. Sur un ordinateur, il est à peu près aussi large que la colonne de cet article, en général plus de 600px, et la boîte est donc bleue. Rétrécissez la fenêtre de votre navigateur jusqu'à ce que le cadre passe sous 600px et elle devient ambre ; la ligne sous la boîte indique la largeur du cadre en direct. Sur un téléphone, le cadre est déjà étroit et vous voyez la version ambre.
La syntaxe @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 demande un espace des deux côtés : (min-width: 600px)and(max-width: 900px) est invalide et toute la requête est ignorée. La syntaxe de plage (width >= 600px) est prise en charge par les versions actuelles de Chrome, Firefox et Safari et se lit plus clairement que min-width, surtout pour « jusqu'à, mais sans inclure ».
Les caractéristiques que vous utiliserez le plus :
| Caractéristique | Correspond quand | Exemple |
|---|---|---|
min-width / width >= | le viewport fait au moins cette largeur | (min-width: 768px) |
max-width / width <= | le viewport fait au plus cette largeur | (max-width: 767px) |
orientation | portrait (plus haut que large) ou landscape | (orientation: landscape) |
hover | le pointeur principal peut survoler (hover) ou non (none, la plupart des écrans tactiles) | (hover: hover) |
pointer | le pointeur principal est fine (souris) ou coarse (doigt) | (pointer: coarse) |
prefers-color-scheme | l'utilisateur a choisi un thème dark ou light | (prefers-color-scheme: dark) |
prefers-reduced-motion | l'utilisateur a demandé au système moins d'animations | (prefers-reduced-motion: reduce) |
print (un type de média) | la page est imprimée ou enregistrée en PDF | @media print |
Mobile first : des breakpoints en min-width
Écrivez la mise en page téléphone comme CSS de base, puis ajoutez des requêtes min-width qui modifient la mise en page quand l'espace augmente. Chaque requête ne décrit que ce qui change :
Dans une large fenêtre d'ordinateur, l'aperçu dépasse 720px et vous voyez trois colonnes ; la ligne sous la grille indique la largeur et le nombre de colonnes. Rétrécissez la fenêtre : on passe à deux colonnes sous 720px et à une sous 480px. L'ordre des deux requêtes compte : elles sont toutes deux vraies sur un grand écran, et la dernière gagne, donc les requêtes min-width vont de la plus petite à la plus grande. (Avec des requêtes max-width, c'est l'inverse : la plus grande d'abord.)
Choisir les breakpoints
Il n'existe pas de liste officielle. Voici des valeurs courantes et ce qu'elles séparent en général :
| Breakpoint | En général |
|---|---|
min-width: 640px | grands téléphones en paysage, petites tablettes |
min-width: 768px | tablettes en portrait |
min-width: 1024px | tablettes en paysage, petits ordinateurs portables |
min-width: 1280px | ordinateurs de bureau |
Une meilleure méthode : partez de la mise en page étroite, élargissez la fenêtre jusqu'à ce que quelque chose rende mal (lignes trop longues, cartes trop larges), et placez un breakpoint à cet endroit. Deux ou trois breakpoints suffisent pour la plupart des pages. Souvent, aucun n'est nécessaire : repeat(auto-fit, minmax(200px, 1fr)) en grid, flex-wrap et clamp() s'adaptent en continu.
Chaque page a besoin de la balise meta viewport
Sans cette balise dans le <head>, les navigateurs de téléphone mettent en page comme si l'écran faisait environ 980px de large, puis dézooment : votre requête min-width: 480px est donc toujours vraie et votre mise en page téléphone ne s'affiche jamais :
<meta name="viewport" content="width=device-width, initial-scale=1">
La page meta viewport explique chacune de ses valeurs.
Mode sombre avec prefers-color-scheme
prefers-color-scheme suit le réglage clair ou sombre du système d'exploitation. La façon la plus propre de l'utiliser est de garder les couleurs dans des variables CSS et de ne changer que les variables dans la requête :
Dans cet aperçu, la requête peut afficher false même si votre système est en mode sombre : Chrome ne transmet pas la préférence du système à un cadre isolé (sandbox) comme celui-ci. Le bouton change les mêmes variables à la main, comme le sélecteur de thème d'un site. :root[data-theme] est plus spécifique que le simple :root de la requête, donc le choix du lecteur l'emporte sur celui du système. Enregistrez l'exemple dans un fichier et ouvrez-le pour voir la requête suivre votre système.
Le script montre l'autre moitié des media queries : matchMedia() exécute la même requête depuis JavaScript, indique si elle correspond maintenant et déclenche un événement change quand la réponse change. Utilisez-la quand un comportement (pas seulement un style) dépend de l'écran, par exemple pour ouvrir un menu différemment sur les appareils tactiles.
Les animations fonctionnent de la même façon. Entourez les animations importantes ou en boucle d'un test sur prefers-reduced-motion, comme le montre la page animation.
Container queries : quand le composant doit décider
Une media query ne connaît que le viewport. Une carte placée à la fois dans une large colonne principale et dans une barre latérale étroite de la même page a plutôt besoin de connaître son propre espace. C'est une container query : marquez le parent avec container-type: inline-size, puis utilisez @container avec les mêmes conditions.
Faites glisser le coin de la boîte grise pour la redimensionner. La carte change de disposition à 360px de largeur de boîte, quelle que soit la taille de la fenêtre :
À ses 480px de départ, l'image est à côté du texte. Rendez la boîte plus étroite que 376px (360px de contenu plus 8px de padding de chaque côté) et l'image passe au-dessus du texte. Les container queries fonctionnent dans tous les grands navigateurs actuels.
Des styles pour l'impression
@media print ne s'applique que lorsque la page est imprimée ou enregistrée en PDF. Masquez la navigation et les boutons, et utilisez un texte foncé sur fond blanc :
@media print {
nav, .ad, button { display: none; }
body { color: black; background: white; }
a::after { content: " (" attr(href) ")"; } /* print the URL after each link */
}
Erreurs courantes
- Pas de balise meta viewport. Les téléphones annoncent alors un viewport de mise en page large et les requêtes pour petits écrans ne correspondent jamais.
- Des requêtes dans le mauvais ordre. Deux requêtes vraies avec le même sélecteur : la dernière gagne. Classez les requêtes
min-widthde la plus petite à la plus grande. - Des limites qui se chevauchent ou laissent un trou.
max-width: 768pxetmin-width: 768pxcorrespondent toutes deux à exactement 768px. Utilisez767pxpour l'une d'elles, ou la syntaxe de plage(width < 768px)et(width >= 768px). - Pas d'espace après
and.and(est invalide et la requête est ignorée sans avertissement. - Tester uniquement en redimensionnant une fenêtre d'ordinateur. Vérifiez aussi sur un vrai téléphone ou avec le mode appareil du navigateur, qui applique le viewport, la densité de pixels et le tactile du téléphone.
- Trop de breakpoints. Si chaque composant a besoin des siens, essayez plutôt grid
auto-fit,flex-wrapou les container queries.
Questions fréquentes
Qu'est-ce qu'une media query en CSS ?
Une règle qui n'applique le CSS qu'elle contient que lorsqu'une condition sur l'appareil ou la fenêtre est vraie. @media (min-width: 600px) { ... } n'applique ses styles que si le viewport fait au moins 600px de large : c'est ainsi qu'une même page s'adapte du téléphone à l'ordinateur.
Faut-il utiliser des media queries min-width ou max-width ?
La plupart des sites sont écrits en mobile first : le CSS de base vise les petits écrans et des requêtes min-width ajoutent de la mise en page quand l'écran s'agrandit. Les requêtes max-width font l'inverse, en partant de la mise en page ordinateur. Les deux fonctionnent ; les mélanger sur le même élément crée des chevauchements et des trous aux limites.
Quels sont les breakpoints standard des media queries ?
Il n'existe pas de standard officiel. Les choix courants tournent autour de 640px, 768px, 1024px et 1280px, mais la meilleure règle est d'ajouter un breakpoint là où votre propre mise en page commence à mal rendre, et d'en garder un petit nombre.
Pourquoi ma media query ne fonctionne-t-elle pas sur téléphone ?
La cause la plus fréquente est une balise meta viewport manquante. Sans <meta name="viewport" content="width=device-width, initial-scale=1">, les navigateurs mobiles font comme si la page faisait environ 980px de large, et les requêtes pour petites largeurs ne correspondent jamais. Vérifiez aussi que la requête vient après les règles qu'elle surcharge.
Comment écrire une media query pour le mode sombre ?
Utilisez @media (prefers-color-scheme: dark) { ... }. Elle correspond quand le système d'exploitation ou le navigateur de l'utilisateur est réglé sur un thème sombre, et vous pouvez y surcharger des couleurs ou des variables CSS.
Quelle est la différence entre media queries et container queries ?
Une media query teste le viewport (toute la fenêtre). Une container query, écrite avec @container, teste la taille d'un élément parent que vous marquez avec container-type: inline-size. Utilisez les container queries pour un composant qui apparaît à la fois dans des emplacements larges et étroits de la même page.