CSS : les media queries - Responsive Web Design

Un site qui s'affiche correctement sur un écran d'ordinateur ou sur une tablette voire un smartphone. Une vue de l'esprit ???
Non pas du tout ! C'est désormais possible à condition d'utiliser dans la feuille de style les media queries (requêtes de média) c'est à dire de produire une feuille de style avec des tests ! On parle de responsive web design (site web adaptatif).

Donc la solution qui consiste à développer plusieurs versions d'un même site et à proposer l'une des versions à l'internaute en fonction de la taille de son écran est une technologie qui peut être évitée.

Prenons un exemple. Imaginons un site dont chaque page comprend quatre grandes divisions :

Le corps de la page (conteneur SECTION) comprend beaucoup de texte répartis dans quatre petites boites (conteneur article).

Oui, j'ai utilisé les nouvelles balises structurantes HTML5.
En HTML4 on aurait eu : div id ="entete, div id ="menu", div id ="corps", div id ="pied"

Aspect attendu de la page sur un grand écran (largeur supérieure à 900 pixels)

Les boites "article" sont toutes de front.

Aspect attendu de la page sur une tablette en mode portrait

Les boites "article" sont deux de front.

Aspect attendu de la page sur un smartphone

Les boites "article" apparaissent les unes en dessous des autres et elles sont "repliées".
Il faut survoler une boite pour la déplier. Les images sont masquées !

Le code HTML : structure

... <meta name="viewport" content= "width=device-width, user-scalable=yes" /> </head> <body> <header>.. </header> <nav>... </nav> <section> ... <article>... </article> <article> ... </article> <article> ... <article> <article>... </article> </section> <footer> ...</footer> </body> </html>

La structure de la page est très simple.
Le conteneur BODY contient les divisions HEADER, NAV, SECTION et FOOTER
La boîte SECTION inclut 4 fois la boite ARTICLE.

Notez cependant dans la partie HEAD une instruction basée sur la balise : meta name = "viewport ... . J'aurai l'occasion de revenir sur cette instruction HTML fondamentale mais un peu compliquée à expliquer ...

La feuille de style avec les media queries (extraits)

@media screen { /* pour tous les écrans */ *{margin: 0px ; padding : 0px ; text-decoration : none ; border : none ; } body {margin-left : auto ; margin-right : auto ; } header, nav, section, footer {width : 100%; border : 1px solid black ; background : lime ; height : auto ; } article {display : inline-block ; background-color : white ; overflow : auto ; } img {display :block ; width : 80%; margin : auto; } ... } /* fin alors */ @media screen and (min-width: 900px) { /* fenêtre d'affichage dont la largeur est au moins égale à 900 pixels */ * {font-size : 14px ;} body {width : 900px ;} header, nav, section, footer {margin-top : 20px ; } article {width : 22% ; margin : 1% ; height : 250px ; } } /* fin alors */ @media screen and (max-width: 900px) and (min-width : 480px ) { /* fenêtre d'affichage dont la largeur est comprise entre 481 et 900 */ * {font-size : 12px ; } body {width : 100% ;} header, nav, section, footer {margin-top : 10px ; } article {width : 44% ; margin : 2% ; height : 150px ; } } /* fin alors */ @media screen and (max-width: 479px) { /* fenêtre d'affichage dont la largeur est inférieure ou égale à 480 */ * {font-size : 10px ; } body {width : 100% ;} header, nav, section, footer {margin-top : 5px ; } article {width : 94% ; margin : 2% ; height : 50px ; } article:hover {height : auto ; } img {display : none ; } } /* fin alors */

Commentaire de cette feuille de style

Grâce aux commentaires le code CSS est assez facile à comprendre.
Les media queries structurent cette feuille de style externe en quatre parties ; chaque partie comprenant des règles de style.

Attention ne confondez pas width (largeur de la fenêtre d'affichage) avec device-width (largeur de l'écran du terminal).

Dans la partie commune à tous les écrans la boite article est redéfinie en inline-block.

Tests

Visualisez la page en lien sur un grand écran puis sur un écran de tablette et enfin sur un écran de smartphone.


Testez la page

Si vous utilisez une tablette orientez celle-ci.
Tantôt vous aurez 4 images de front (orientation paysage) et tantôt 2 images de front (orientation portrait).

Plusieurs feuilles de style

Plutôt qu'une seule feuille de style externe on peut utiliser HTML pour rediriger en fonction de la largeur de l'écran vers un des différents fichiers CSS.
Dans la partie HEAD vous trouveriez le code suivant :

<link rel ="stylesheet" href ="style_commun.css" media ="screen" /> <link rel ="stylesheet" href ="style_petit.css" media ="screen and (max-width:479px)" /> <link rel ="stylesheet" href ="style_moyen.css" media ="screen and (max-width: 900px) and (min-width : 480px )" /> <link rel ="stylesheet" href ="style_grand.css" media ="screen and (min-width : 900px )" />

Donc au lieu d'une feuille de style externe il y a 4 fichiers CSS.
Le code HTLM charge toujours la feuille "style_commun.css" et l'un des trois autres fichiers en fonction de la largeur de l'écran.

La balise META dans la partie HEAD

Vous avez sans doute remarqué que la partie HEAD de la page il y a une instruction HTML très étrange :

<meta name="viewport" content = "width=device-width, user-scalable=yes" />

A quoi sert cette instruction ?
Cette instruction est fondamentale dans le cadre du Web mobile !

Les écrans des mobiles sont beaucoup plus étroits que les écrans de PC (seulement quelques centaines de pixels de large). Pour s'adapter, les navigateurs mobiles affichent le site en "dézoomant" ce qui permet d'avoir un aperçu de l'ensemble de la page mais alors c'est c'est tellement écrit petit que c'est illisible ...

Cette zone d'affichage simulée est appelée le viewport.

Attention la valeur du viewport ne dépend pas du terminal mais du navigateur mobile installé sur ce terminal.
Ainsi le viewport est compris entre 800 pixels (Android 3) et 980 (Android 4 et Safari).

Prenons un exemple. Votre iphone5 a une largeur utile d'écran de 320 par 568 pixels ; le viewport possible est de 980 pixels grâce au navigateur safari mobile qui est installé.
Mais grâce à l'instruction meta name ="viewport" ... la largeur effective sera de 320 pixels ou (568 selon l'orientation).

Les images

Pour que les images ne soient jamais rognées sur un petit écran tel celui d'un smartphone il ne faut pas exprimer leur largeur en pixels mais en pourcentage (de la largeur du parent).

Exemple

<style> body {width : 90% ; margin : auto ; } img.grand {display : block ;width : 80% ; margin : 10px auto 10px auto; } img.petit {display : inline-block ;width : 40%; margin :1% ; } ... <body> <p>Une grande image centrée dans son container : <img src ="..." class ="grand" /> ... <p>Deux petites images de front : <img src ="..." class ="petit" /> <img src ="..." class ="petit" /> ...

Ainsi la largeur de chaque image va s'adapter à celle du conteneur parent (BODY) qui lui même a une largeur fonction de l'écran (900 pixels si grand écran ou 100% si petit écran).

Les images vectorielles et le Responsive Web Design

Pour que les images vectorielles (format SVG) produites avec un éditeur de textes (ou avec Inkscape ou les deux) ne soient jamais rognées sur un petit écran il suffit de modifier certains attributs de la balise SVG.

Imaginons qu'avec Inkscape vous avez créé un document de 600 par 400 pixels.
Dans le code de la balise SVG on retrouve entre autres : ...width ="600" height="400"

Avant d'insérer cette image dans une page web il faut le modifier comme suit le code du fichier SVG :

<svg ... width ="100%" height="auto" viewBox ="0 0 600 400" >

La taille de l'image SVG s'adapte ainsi à la largeur de l'écran. Mais pour que les formes contenues dans l'image vectorielle puissent être dessinées il faut impérativement un système de coordonnées ; il faut donc rajouter un viewBox !

Les zones de dessin Canvas et le Responsive Web Design

L'API Canvas vous permet de produire un dessin (statique ou animé) dans une page web.
Même problématique qu'avec une image vectorielle SVG : la zone de dessin Canvas doit s'afficher proprement même sur un petit écran.
Il suffit de définir une taille "officielle" du canevas avec les attributs width / height de la balise CANVAS puis de définir les dimensions d'affichage du canevas via une règle de style (propriétés CSS width / height).
Exemple :

<canvas width ="600" height ="400" style ="width :80% ; height : auto ;"></canvas>

La zone de dessin CANVAS va s'afficher conformément au CSS (largeur du canevas = 80%) mais pour le script la zone de dessin fait 600px par 400px. Ainsi si dans le script vous avez les instructions suivantes :
Retour menu