Tout savoir sur les media queries pour un site responsive design réussi

Sommaire

Sur les media-quoi ? Responsive design ?

Bon, si vous êtes ici c'est que vous avez déjà au moins entendu parler de ces termes, et probablement que vous savez également de quoi il s'agit. Pour les autres, voici un petit récapitulatif !

Je vais commencer par vous parler du "responsive design". On en a beaucoup entendu parler ces dernières années, avec l'arrivée, et même l'explosion sur le marché, des smartphones. Il s'agit tout simplement, comme son nom l'indique pour les anglophones, d'un site, d'une application, qui s'adapte au support sur lequel il est affiché. D'où le lien avec les smartphones, qui peuvent très bien afficher des sites mais qui ont un écran plus petit que ce nous connaissions jusque là.

Et les media queries ? Eh bien il s'agit de conditions qui permettent d'appliquer tels ou tels styles en fonction du contexte où la page est affichée. Comme il s'agit du sujet de cet article, j'y reviendrai plus en détails par la suite !

Des smartphones, mais pas seulement

J'ai évoqué les smartphones (et par extension les tablettes) juste avant pour expliquer la grande hausse de popularité et la démocratisation du responsive design. Mais ce dernier existait bien avant l'ère du smartphone. Le responsive design s'étend à d'autres choses, plus communes qu'on ne pourrait le penser. Par exemple l'impression (où on souhaiterait retirer les images de fond, le menu, ajouter l'attribut "href" après les liens...).

Avant de commencer : la balise meta viewport

Pour que les media queries fonctionnent correctement, elles doivent se rattacher à quelque-chose, une définition de base. Pour ça, il convient de rajouter une balise <meta> dans la page, afin de définir quelle est la largeur de la page, ainsi que son niveau de zoom. Les paramètres les plus communs de cette balise sont les suivants :

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Ils permettent ainsi d'indiquer que la largeur du viewport est celle de l'écran, à sa taille réelle. C'est sur ces information que se baseront les media queries par la suite.

Comment utiliser des media queries pour rendre son site responsive design ?

Nous y voilà ! Avant de répondre à cette question, je vais vous indiquer à quoi ça ressemble avec un exemple de media query :

screen and (max-width: 960px)

Celle-ci cible les écrans dont la largeur est inférieure à 960 pixels. Vous voyez, en soit ça reste assez simple à comprendre :)

Retenez bien cet exemple, vous allez le revoir dans les paragraphes qui suivent ;)

Donc pour leur mise en place, il y a plusieurs façons de faire, selon ce que l'on souhaite faire :

Dans la feuille de styles CSS

Une des possibilités consiste à intégrer des styles CSS dans les media queries, en insérant celles-ci directement dans la feuille de styles. Les media queries seront alors précédées de @media, et suivies de crochets dans lesquels on mettra tous les styles qui seront appliqués quand la media query est valide.

Si vous lisez ceci vous le savez sûrement déjà, donc je vous rappelle seulement sans plus rentrer dans les détails qu'il existe des règles de priorités dans le CSS. À niveau égal, ce sont les dernières propriétés qui sont prises en compte. Sinon ce sont celles qui sont déclarées de façon plus précises via les id, classes... (ou celles qui sont affublées d'un !important). On peut donc se servir de ce principe pour par exemple préparer une feuille de style globale pour un site desktop (ou mobile si on est plutôt de l'école "mobile first"), puis la "patcher" grâce à des media queries.

Voici donc comment ça marche :

body{ background-color: red; }
@media screen and (max-width: 960px){
    body{ background-color: green; }
}

Dans l'exemple ci-dessus, la couleur de fond du site sera rouge. Mais si l'écran a une largeur inférieure à 960 pixels, là le fond sera vert. Et voilà, vous avez le principe de base du responsive design !

Dans les balises HTML

Un autre moyen d'utiliser les media queries est de les déclarer dans certaines balises HTML, grâce à l'attribut media. On peut par exemple créer un fichier CSS dédié à une taille d'écran, puis l'appeler dans une balise <link> comme ceci :

<link type="text/css" rel="stylesheet" media="screen and (max-width: 960px)" href="mobile.css" />

Ici, la feuille de styles mobile.css ne sera appelée que si la taille d'écran est inférieure à 960 pixels. Là aussi vous pouvez bien sûr cumuler les balises.

Un autre cas d'utilisation des media queries dans une balise HTML, c'est dans la balise <source>, elle même contenue dans une balise <picture>. Elle nous permettra alors de choisir un fichier à utiliser en fonction du contexte.

Avec du javascript

Enfin, il est également possible de vérifier une media query en javascript, à l'aide de la fonction window.matchMedia() qui retourne un objet dont une propriété et une méthode vont plus particulièrement nous intéresser.

Tout d'abord, la propriété matches : elle vaut true ou false selon le résultat de la media query. On peut donc réaliser un script basique de ce genre :

if( window.matchMedia("screen and (max-width: 960px)").matches ){
    // code qui sera exécuté si l'écran est plus petit que 960 pixels
}else{
    // sinon c'est ce code qui sera exécuté, enfin vous connaissez les bases if/else, quoi :)
}

C'est pratique pour vérifier l'état d'une media query à l'instant T (ou plutôt I). Mais là où ça devient encore plus intéressant c'est que cette fonction permet de détecter le changement d'état de la media query. On peut alors procéder ainsi :

window.matchMedia("screen and (max-width: 960px)").addListener(ma_fonction);
function ma_fonction(){
    // la fonction ma_fonction() (vous pouvez évidemment choisir le nom hein)
    // sera exécutée lorsque la media query passe de false à true et vice-versa
}

Bon, après on change rarement de type de media ou de résolution en cours de route. Mais ça peut servir à détecter le changement l'orientation par exemple, ou de largeur d'écran (enfin plutôt de fenêtre, de "viewport" pour être précis).

Voilà, vous savez maintenant détecter une largeur d'écran maximale de 960 pixels à toutes les sauces ! Maintenant voyons quels autres ingrédients vous pourrez utiliser pour assaisonner vos media queries dans les chapitres suivants.

La syntaxe d'une media query et les opérateurs logiques

Les media queries sont constituées de types, d'opérateurs logiques, et/ou de "media features". Elles peuvent être combinées en les séparant par une virgule, comme avec l'exemple suivant :

screen and (min-width: 420px) and (max-width: 960px), print

Si une des conditions est vraie, alors toute la chaîne est valide. Un peu comme si la virgule était un "ou". Donc dans mon exemple, ce qui y est rattaché sera appliqué sur un écran d'une largeur comprise entre 420 et 960 pixels OU à l'impression. Si à l'inverse j'avais écris ceci :

screen and (min-width: 420px), screen and (max-width: 960px), print

Ma requête serait valide à l'impression, ou sur un écran quelle que soit sa taille. En effet, celle-ci est toujours soit inférieure à 960 pixels, soit supérieure à 420 pixels (ou soit les deux) !

L'opérateur and

On vient de l'utiliser, et vous vous en doutiez déjà, il sert à lier deux conditions au sein d'une requête. Celle-ci n'est vraie que si toutes les conditions reliées par and sont remplies. Si je reprends mon exemple initial :

screen and (max-width: 960px)

Cette requête ne sera valable que si on est sur un écran ("screen"), et que celui-ci a une largeur maximale de 960 pixels ("max-width: 960px").

À propos je n'arrête pas de parler de largeur d'écran, mais notez bien que c'est un abus de langage. Pour être exact il s'agit de la largeur du "viewport" : la zone dans laquelle votre site ou application apparaît. La taille de votre écran restera fixe, alors que la fenêtre qui s'y trouve pas forcément ;)

L'opérateur not

Cet opérateur est à mettre en début de media query, et il sert tout simplement à vérifier l'inverse. Par exemple :

not screen and (max-width: 960px)

Les styles et sources associés ne seront appliqués que si on n'est pas sur un écran d'une largeur inférieure à 960 pixels. Ce qui n'implique pas seulement les écrans plus grands, mais aussi les autres types de médias ;)

Ah, et dernière chose, si vous utilisez not vous devez également mettre un type de media. not (max-width: 960px) ne sera pas valide !

L'opérateur only

Celui-ci est un peu un cas à part. On le croise souvent, mais vu le peu d'infos claires que l'on trouve là-dessus je pense qu'une certaine partie des intégrateurs l'utilise sans trop savoir pourquoi ^^. Enfin bref, ce n'est pas bien grave, puisque de toutes façons ça ne fait plus de grande différence aujourd'hui. Car à la base, il est utilisé pour faire en sorte que certains vieux navigateurs n'interprètent pas les styles qui y sont associés. Je m'explique : certains d'entre eux ne reconnaissent pas la syntaxe telle qu'on vient de le voir. Ils ne reconnaissent que le premier mot de chaque requête séparés par des virgules. Ainsi, si je reprends un de mes exemples, screen and (min-width: 420px) and (max-width: 960px), print sera compris ainsi : screen, print. Et ça peut être embêtant dans certains cas !

C'est là qu'intervient only, qui comme not doit toujours être placé en début de requête. only sera alors considéré comme un type (cf. ci-après) mais ne correspondant à rien il est alors ignoré. Concrètement, ça se passe comme ça : on a une media query screen and (max-width: 960px), qui permet d'appliquer des styles ou sources propres à un écran de petite taille. Sur certains vieux navigateurs, c'est donc interpété en screen, et donc les styles ou sources associés s'appliquent dès lors qu'on est sur un écran, même d'une taille supérieure à 960 pixels. Si on ajoute only à la media query, only screen and (max-width: 960px), ces navigateurs comprendront only et ignoreront tout simplement les styles et sources associées.

Cibler des medias avec les différents types

Allez, maintenant un peu de vocabulaire ! J'en ai parlé tout au long de l'article, voici la liste complète des types de média !

screen

Le plus commun, permet de cibler un affichage sur écran, quel qu'il soit (ordinateur, smartphone, télé...)

print

Son utilisation permet de cibler les impressions. Comme je l'ai vaguement expliqué en début d'article, on s'en servira notamment pour adapter et optimiser le site pour une sortie papier (ou PDF) en enlevant les éléments inutiles, en optimisant les couleurs et les images pour économiser l'encre, en écrivant l'url des liens après ces derniers, en évitant les veuves et orphelines, etc.

speech

Cas plus particulier qui correspond aux outils de synthèse vocale, notamment utilisés pour les malvoyants qui consultent un site internet. Vous pourrez alors "styliser" la voix : sa vitesse, son intonation, son volume, la lecture ou non de la ponctuation... À utiliser avec parcimonie quand même, en général on s'habitue aux paramètres de son outil et certains changements peuvent être perturbants au dépens de l'information fournie.

all

Englobe tous les types de média vus précédemment !

C'est tout ? Il en manque non ? J'ai vu qu'il existait également aural, braille, embossed, handheld, projection, tty et tv !

Oui c'est tout. Aural est devenu speech, quant aux autres ils ont été dépréciés depuis qu'on est passé en CSS 3.

Jouer avec les media features

Les media features c'est la partie que vous avez vue entre parenthèses au cours des différents exemples. Elles doivent d'ailleurs toujours s'écrire entre parenthèses, avec cette syntaxe : ( propriété : valeur ).

Dimensions et formats d'affichage :

width, min-width et max-width

Permet de conditionner ce que j'ai passé mon temps à appeler la largeur d'écran, mais qui pour être exact concerne la largeur de la fenêtre (le "viewport"). Doit prendre pour valeur une dimension, peu importe l'unité (bon, à part peut-être les "vw" et les "vh", puisque la largeur de la fenêtre fera toujours 100vw et 100vh). Les anciennes propriétés device-width et variantes ont été dépréciées, elles sont maintenant obsolètes.

height, min-height et max-height

Exactement comme width et ses variantes, mais cette fois-ci basé sur la hauteur de la fenêtre :)

Et là aussi, device-height, précédé ou non de min- et max-, est à oublier.

aspect-ratio, min-aspect-ratio et max-aspect-ratio

Cette propriété permet de cibler certaines proportions de la fenêtre. Vous connaissez tous les écrans 16/9 ? Eh bien c'est exactement de ça qu'il s'agit : un rapport largeur/hauteur. La valeur de cette propriété doit s'écrire avec deux entiers (donc ou oubliera 1,78/1) séparés par "/". Par exemple, (min-aspect-ratio: 4/3) ciblera les fenêtres dont le rapport largeur/hauteur est de 4/3, ainsi que les fenêtres plus larges.

Comme pour width et height, il existait son ancêtre déprécié device-aspect-ratio et ses variantes.

orientation

Cette propriété est simple, et vous vous en doutiez déjà elle concerne l'orientation de la zone d'affichage (ou de la page si vous êtes sur un media print). Je dis simple parce qu'elle ne prend que deux valeurs : portrait (donc portrait, vertical, "à la française", debout...) et landscape (paysage, horizontal, "à l'italienne", couché... c'est fou le nombre de mots pour qualifier un concept précis ^^).

resolution, min-resolution et max-resolution

Son utilité est aussi facile à deviner que la précédente (ben oui, la résolution de l'affichage, que ce soit en media screen ou print). Mais les valeurs sont un peu plus compliquées à prendre en main, puisque plusieurs unités assez peu intuitives sont possibles :

  • dpi : points par pouce (dots per inch). Si vous jonglez entre print et web, vous avez sûrement entendu des choses comme "les images pour le web sont en 72dpi, pour le print elles sont en 300dpi". Ce qui n'est d'ailleurs plus tout à fait vrai avec les écrans retina, mais c'est en gros l'idée.
  • dppx ou juste x : points par pixel. Ça peut sembler abstrait, mais c'est peut-être l'unité la plus pratique pour cibler un écran rétina par exemple.
    Si vous aimez les explications compliquées, comme la résolution par défaut des images en CSS est de 96dpi et que 1in (inch, je précise car je doute que vous utilisiez souvent cette unité !) en css = 96px, on en déduit que 1 "dot" = 1 "pixel" sur un écran standard à 96dpi (puisqu'il y a alors autant de points que de pixels dans un pouce), donc dans ce cas (écran à 96dpi), on est sur une résolution de 1dppx.
    Ce qu'il faut surtout retenir, c'est que 1dppx = 96dpi. Vous pouvez alors considérer cette unité comme un "multiplicateur" de résolution. Sur un écran retina où la résolution est deux fois plus élevée que le standard, on passe alors sur du 2dppx. En ça, la notation abrégée est encore plus facile à prendre en main puisque vous pouvez vous imaginer écrire "deux fois (2x) la résolution standard".
  • dpcm : points par centimètre. Je ne vois pas trop l'intérêt de cette unité, même sur un media print, mais elle existe. Pour info, 1 in = 2,54 cm si vous voulez convertir les dpi en dpcm ;)

Type d'affichage et couleurs :

Les propriétés de cette partie sont relativement peu utilisées. En tout cas elles concernent seulement une infime part du marché des affichages de sites ou applications. Il y en a même certaines dont je me demande même quels appareils sont concernés ! Il y en a d'autres qui ne sont comprises que par très peu voire aucun navigateur actuel. Je vous ai déjà pas mal noyé dans les propriétés qui concernent l'affichage parce que ça reste la majeure partie de ce qui est utilisé pour le responsive design. Je vais donc moins rentrer dans les détails et les exemples de cette partie. Et aussi parce que n'ayant jamais eu à utiliser une de ces propriétés, je les maîtrise moins :)

grid

Cette propriété permet de détecter le mode d'affichage de l'écran. S'il s'agit d'une "grille" (souvent l'affichage est juste du texte de type monospace sur un terminal relativement basique) ou non (la plupart des écrans que vous connaissez). Les valeurs possibles sont respectivement 1 et 0.

color, min-color et max-color

Permettent la détection du nombre de bits pour chaque composant de couleur (donc pour le rouge, le vert et le bleu, et non pas pour l'ensemble). Si l'appareil ne gère pas les couleurs, on peut le détecter avec (color: 0). Pour un écran standard on utilisera plutôt (color) (ce qui équivaut à (min-color: 1)) voire (min-color: 8), puisque dans notre système habituel on utilise 8 bits par composant de couleur (de 00000000 à 11111111 en binaire, donc de 0 à 255 en décimal ou de 00 à FF en hexadécimal).

color-gamut

Ici on touche également à la colorimétrie, mais cette fois-ci on se base sur le nombre de couleurs supportés par l'écran. Les valeurs possibles sont srgb (la valeur la plus commune, qui est déjà très vaste), p3 (pour DCI P3, un espace plus grand et incluant sRGB), et enfin rec2020 (Rec. 2020, avec encore plus de couleurs disponibles, et là aussi incluant DCI P3, et de fait sRGB). À l'heure où j'écris cet article, cette propriété est interprétée à partir de Chrome 58, Safari et Opéra 45, mais pas sur Firefox ni Internet Explorer (et je n'ai pas trouvé l'info pour Edge)

monochrome, min-monochrome et max-monochrome

Ces propriétés ciblent le nombre de bits utilisés pour l'affichage monochrome du support. Si ce dernier n'est pas monochrome, alors on le cible avec (monochrome: 0). Sinon, on cible un affichage monochrome avec (monochrome), l'équivalant de (min-monochrome: 1).

Il existe également scan, update, overflow-block, overflow-inline, color-index ou encore inverted-colors, qui ne sont pas (encore ?) compatible avec les différents navigateurs.

Possibilités d'interactions :

Les propriétés que je vais vous présenter ici sont intéressantes dans le sens où en terme d'UX on peut parfois se retrouver coincé à cause d'un responsive design mal pensé au niveau des interactions, notamment via la souris. Il y a encore peu, elles n'étaient pas supportées par Firefox. Mais ça a été réglé avec la sortie de sa version 64. Elle n'est pas non plus compatible avec Internet Explorer (Edge, si), mais bon... on a appris à ne pas trop compter sur lui, même si c'est moins vrai qu'il y a quelques années :)

Actuellement en France, ces propriétés sont fonctionnelles pour environ plus de 96% des utilisateurs sur mobile, contre environ 90% pour les autres (desktop). On préférera donc les utiliser pour détecter l'absence de souris plutôt que sa présence, pour faire simple.

pointer et any-pointer

Ces deux propriétés permettent de détecter ou non la présence d'un dispositif de pointage (donc principalement une souris, mais également un stylo de tablette graphique, votre doigt...) ainsi que son niveau de précision. Les valeurs possibles sont :

  • none : aucun dispositif de pointage, par exemple un contrôle uniquement au clavier, à la manette rétro (sans joystick)...
  • coarse : dispositif de pointage, mais pas très précis ! C'est le cas par exemple d'un écran tactile, d'une manette de Wii, Kinect...
  • fine : vous l'aurez deviné, on est là sur une détection d'un dispositif de pointage précis : souris, stylo de tablette graphique, touch pad...

La différence entre pointer et any-pointer est que ce second détecte si n'importe quel dispositif de pointage est concerné, et le premier uniquement le dispositif principal.

hover et any-hover

Cette fois-ci, on permet de détecter si le dispositif de pointage permet de survoler des éléments ou non. Ça aurait pu être un booléen, mais non : none lorsque le survol n'est pas possible (ou il n'y a tout simplement aucun dispositif de pointage), et hover si le survol est possible. :)

La différence entre hover et any-hover est la même que pour pointer et any-pointer.

Attention cependant : testez bien vos media queries. En ce qui me concerne mon smartphone est considéré comme ayant un dispositif permettant le survol (en fait il applique le survol au moment de toucher l'écran, donc potentiellement en même temps qu'un "clic"), donc j'aurai plutôt tendance à n'utiliser que pointer et pas hover.

Et à l'avenir ?

Il existe encore quelques propriétés embryonnaires, qui ne sont actuellement disponibles sur aucun navigateur. Il faudra attendre les media queries de niveau 5 pour ça, ainsi que le réveil des navigateurs retardataires qui n'auront pas bien préparé ça ^^. À l'avenir, il sera donc possible de détecter, grâce aux media queries, la luminosité ambiante de l'appareil (un peu comme le mode nuit des GPS) avec justement une ambiance sombre, idéale, ou très lumineuse (extérieur en plein soleil par exemple) grâce à la propriété light-level. Également, la détection de la disponibilité d'outils de script (notamment Javascript) via la propriété scripting. Et enfin, plusieurs réglages utilisateurs (qui seront probablement basés sur ceux du navigateur ou du système d'exploitation) tels que moins de mouvements (prefers-reduced-motion), moins de transparence (prefers-reduced-transparency), plus ou moins de contrastes (prefers-contrast), et le choix d'un thème plutôt clair ou foncé (prefers-color-scheme). Ce dernier est d'ailleurs utilisé sur ce site, il s'adapte donc à vos préférences de couleurs définis sur votre système d'exploitation :)

Alternative pour les images avec srcset

Enfin, il est également possible avec uniquement du HTML de proposer au navigateur plusieurs images à afficher selon le contexte, dans une balise <picture> ou <img>. Si ça vous intéresse, découvrez ça ici :

Si vous avez trouvé cet article intéressant, pourquoi ne pas le partager ? :)
Facebook Messenger Twitter LinkedIn Viadeo Reddit Email

Vous avez une remarque, une précision à apporter, ou quelque-chose vous échappe ?
N'hésitez pas à participer à cet article, cet espace est pour vous !

Un commentaire

Merci pour ces explications

Commenter, poser une question...

 

Ces articles pourraient également vous intéresser

Une image toujours adaptée avec srcset et sizes

Saviez-vous que le responsive design n'est pas qu'une histoire de css, voire de javascript ? Découvrez comment proposer la meilleure image uniquement en HTML !

Lire l'article Une image toujours adaptée avec srcset et sizes

Des styles CSS pour optimiser l'impression papier

Quelque-chose qui est souvent oublié sur un site, c'est que les internautes peuvent décider de l'imprimer. Je vais ici vous donner quelques astuces pour réaliser une feuille de styles "basique" pour l'impression.

Lire l'article Des styles CSS pour optimiser l'impression papier

Le web du futur #1 : un affichage qui varie en fonction de la luminosité

À l'avenir, vous pourrez détecter la luminosité ambiante de l'appareil grâce à la media query light-level. Cet article vous explique pourquoi ça peut être utile et comment l'utiliser.

Lire l'article Le web du futur #1 : un affichage qui varie en fonction de la luminosité
Remonter