Outils CSS pour le responsive design

Alexandre Niveau
GREYC — Université de Caen
En partie adapté du cours de Jean-Marc Lecarpentier
TODO: multicolumn est bien supporté maintenant
TODO: parler de span pour grid pour les L1 ?

Contexte

Jusqu'en 2007, un site web se visitait sur un écran d'ordinateur
  • Différentes tailles d'écran, mais pas suffisamment importantes pour qu'un design prévu pour une largeur de 800 pixels soit vraiment inadapté
  • Quelques terminaux mobiles (PDA, Blackberry), mais rares, et affichent les pages web assez différemment

Arrivée de l'iPhone, puis des autres smartphones, puis des tablettes : les sites web doivent s'adapter à de multiples tailles d'écran

En parallèle, taille et définition des écrans d'ordinateur augmente

Il n'est plus pertinent de proposer une « version mobile » et une « version desktop » de son site web…

un seul site, qui doit s'adapter à toutes les possibilités

Responsive design

  • « Design adaptatif » : styles qui s'adaptent en fonction de la place disponible, de la résolution, de l'orientation de l'écran…
  • Adaptabilité en termes de :
    • mise en page : colonnes, placement des menus
    • contenu : montrer plus ou moins en fonction de l'espace
    • images : réduire leur taille
    • polices : à adapter selon l'écran

Media queries

  • Objectif : appliquer des règles CSS uniquement lorsque certains critères sont remplis
  • Exemple : « lorsque la largeur de la fenêtre est en-dessous de 800 pixels, je veux que mes paragraphes soient en jaune sur fond noir »
    @media (max-width: 800px) {
      p {
        background: black;
        color: yellow;
      }
    }
    
  • N.B.: la règle spéciale @media contient des règles CSS !
  • Référence complète : Media Queries W3C Recommendation

Critères possibles

Les propriétés sont de la forme critère: valeur

Nombreux critères possibles :
  • Couleur : color, color-index, monochrome
  • Caractéristiques de l'appareil (valeurs fixées) : device-height, device-width, device-aspect-ratio, resolution
  • Affichage (valeurs dynamiques) : height, width, orientation, aspect-ratio

La plupart des critères peuvent prendre les opérateurs min- et max-

Par exemple, min-width: 400px signifie « largeur supérieure à 400px » (autrement dit, la largeur minimale pour laquelle la propriété s'applique est 400px)

Format des requêtes

@media type and (propriété) and (propriété) etc.

Attention aux espaces et parenthèses : seul le type n'est pas entouré de parenthèses

Types : screen, print,braille, embossed, aural

Pour sélectionner tous les types : all, ou alors ne pas mettre de type du tout
@media all and (min-height: 200px)
@media (min-height: 200px)
Les deux requêtes précédentes sont équivalentes.

Si la requête commence par not, elle est inversée : @media not screen and (max-width: 60em) est appliquée si le média n'est pas un écran de moins de 60em (donc elle s'applique par exemple à l'impression et aux écrans de plus de 60em)

On peut faire plusieurs requêtes en même temps en les séparant par des virgules :
@media (max-width: 300px), not print and (color), screen and (min-resolution: 300dpi)

Utilisation des requêtes média en pratique

En pratique, on ne va quasiment utiliser que max-width et min-width

Si on met des media queries un peu partout dans son CSS et dans plusieurs sens (max/min), impossible de s'y retrouver !

On va plutôt avoir un CSS de base, modifié ensuite avec des requêtes média — si possible dans une seule direction

Soit on part de la version mobile et on fait des modifications pour des largeurs de plus en plus grandes, soit l'inverse

Exemple (simpliste) :
/* version par défaut: sur grand écran */
.menu { width: 30em; /* etc. */ }

/* écran plus petit: on passe le menu en horizontal */
@media (max-width: 100em) {
	.menu { width: 100%; }
	.menu li { display: inline-block; }
	/* etc. */
}

/* écran encore plus petit: on cache le menu */
@media (max-width: 50em) {
	.menu { display: none; }
}

Requêtes média dans le HTML

Remarque : on peut aussi utiliser les media queries dans l'attribut media de l'élément link, pour choisir quelle feuille de style charger

<link rel="stylesheet" media="print" href="print.css" />
<link rel="stylesheet" media="screen" href="all_screens.css" />
<link rel="stylesheet" media="screen and (max-width: 600px)"
                       href="small_screens.css"
/>

Ajustement automatique

  • Navigateurs mobiles : zoom automatique pour ajuster la page dans la largeur. À désactiver seulement si votre site est responsive !
  • Cela se fait dans le HTML avec une balise meta :
    <meta name="viewport" content="initial-scale=1" />
  • On voit beaucoup
    <meta name="viewport" content="initial-scale=1, width=device-width" />
    mais a priori ça n'apporte rien de plus que initial-scale=1 (et ça pourrait même poser des problèmes pour les appareils en mode paysage ?), à tester… — quelques détails
  • Autre valeur possible, pour empêcher l'internaute de modifier le niveau de zoom (uniquement sur terminal mobile) :
    <meta name="viewport" content="maximum-scale=1.0,
                                   minimum-scale=1.0" />
    
    Très déconseillé (sauf si vous savez ce que vous faites) : la possibilité de zoomer est indispensable pour l'accessibilité !
  • Plus de détails sur le viewport dans cet article en français
NB: @viewport en CSS a été abandonné (pb de performances pour le chargement des images)

Largeur adaptable sans requête media

  • On peut utiliser les propriétés CSS max-width et min-width
  • Exemple, pour que le body ne fasse jamais plus de 60 em de large :
    body { max-width: 60em; }
    
    ou pour que le menu fasse 30% de la largeur de l'écran, mais ne soit ni trop petit ni trop grand :
    #menu {
      width: 30%;
      max-width: 50em;
      min-width: 10em;
    }
    
    ou pour que les images ne dépassent jamais de leur conteneur (et donc ne soient jamais plus larges que l'écran) :
    img { max-width: 100%; }
    
  • Dans les cas complexes où on donne des valeurs « dynamiques » aux trois propriétés, max-width gagne contre width mais perd contre min-width
  • La façon dont la largeur finale est calculée peut être complexe à comprendre, voir la spécification
  • Pas grave, en général seuls les cas simples (comme les exemples ici) nous intéressent

Calculs en CSS sans requête media

  • Fonction CSS calc() permet d'utiliser le résultat d'un calcul (pas trop compliqué) comme valeur d'une propriété
  • Permet de mélanger les unités
  • Peut être utile pour s'en sortir quand certaines parties sont de taille fixée et d'autres de taille variable
  • Exemple :
    .bidule {
      width: calc(100%/3 - 200px - 2*10em);
    }
  • Utilisable partout sauf Opera sur mobile
  • Détails : recommandation W3C
parler de min, max, clamp ? https://web.dev/articles/min-max-clamp

Unités de longueur : rappel

  • Recommandation W3C
  • Pas besoin d'unité pour zéro
  • Longueur absolue :
    • pt : point, utilisé pour les médias destinés à l'impression
    • in : pouce (2,54cm, 1/72in = 1pt)
    • px : pixel = 1/96 in (un pixel CSS peut recouvrir plusieurs pixels de l'écran)
    • mm, cm
  • Longueur relative : taille calculée par rapport à l'élément parent
    • em : taille dépendant de la police de caractères.
    • % : relatif au bloc parent (par ex. taille de la police du bloc parent, largeur du bloc parent)

Unités de longueur pour le responsive design

  • Compromis entre relatif et absolu : rem, correspond à la valeur font-size de l'élément racine
  • Unités de longueur qui dépendent de la taille de la fenêtre :
    • vw: 1% de la largeur courante de la fenêtre (viewport width)
    • vh: 1% de la hauteur courante de la fenêtre (viewport height)
    • vmin: correspond au plus petit entre vw et vh
    • exemple, on veut un carré qui tienne dans la fenêtre
    • vmax: correspond au plus grand entre vw et vh
  • Par exemple, si la fenêtre fait 1200 pixels de large, un vw vaut 12 pixels
  • C'est une unité comme une autre ! Techniquement, rien n'empêche d'utiliser des vw et des vh partout à la place des px ou des em
  • Explications sur l'intérêt de ces unités (en particulier pour la taille de police et pour la hauteur des blocs)
tout un tas de nouvelles unités responsive ont été introduites, mais pas utiles pour la L1 a priori

Texte en colonnes

  • Les humains lisent mieux un texte avec des lignes courtes (entre 60 et 100 caractères), c'est pourquoi les publications papier utilisent des colonnes
  • Impossible de reproduire cet effet en CSS2 sans fixer la hauteur ⇒ problème pour la responsivité
  • Solution : module CSS3 « multi-column layout » (tuto en français)
  • Très flexible et complet
  • Maintenant bien supporté par les navigateurs

Taille des images

  • Un des gros problèmes actuellement pour le design adaptatif : la taille des images
  • Écran à très haute résolution = même taille mais beaucoup plus de pixels
  • Images normales sont pixelisées sur un écran à double résolution… mais on ne peut pas demander à tout le monde de télécharger des images 4 fois plus grosses
  • Même problème pour des images dont la taille change en fonction de la largeur de l'écran (c'est-à-dire à peu près toutes les images pour un site adaptatif…)
  • On peut aussi vouloir présenter l'image différemment (recouper, tourner… ou même changer d'image) en fonction de la taille de l'écran ⇒ problématique de direction artistique

Solution pour adapter la taille

  • Attribut srcset pour img, donne les URL de plusieurs images, avec des informations
    <img srcset="normal.jpg 1x, hd.jpg 2x"
         src="normal.jpg" alt="Texte alternatif" />
    <img srcset="petite.jpg 400w, moyenne.jpg 800w, grande.jpg 1200w"
         src="moyenne.jpg" alt="Texte alternatif" />
  • 1x, 2x : indique la résolution. Adapté pour les images de taille fixe.
  • 350w : indique la largeur de l'image en pixels. Adapté pour les images dont la taille dépend de celle de l'écran.
  • Principe fondamental : on laisse le navigateur décider quelle image télécharger, en fonction des caractéristiques du terminal (résolution et taille de l'écran)
  • Bien supporté sur les navigateurs modernes
Démo version CSS (pour sélectionner les images de fond): fonction image-set(). expérimental (voir tous les problèmes cités dans la spéc), implémenté seulement dans Chrome avec préfixe.

Solution pour la direction artistique

  • Élément picture, permet de choisir l'image chargée en fonction de media queries
    <picture>
    	<source media="(min-width: 36em)" srcset="img/ethiopian-wolf.jpg" />
    	<source srcset="img/ethiopian-wolf_icon.jpg" />
    	<img src="img/ethiopian-wolf.jpg" alt="Another reddish wolf" />
    </picture>
  • Compatible avec srcset, pour pouvoir adapter à la fois le design et la résolution
Démo

Guide de srcset et picture

Tuto MDN sur les bases

Paliers

Content is like water. You put water into a cup it becomes the cup. You put water into a bottle it becomes the bottle. You put it in a teapot, it becomes the teapot.
Illustration par Stéphanie Walter (licence CC-BY-SA)
  • Aux débuts du responsive design, seulement quelques largeurs d'écran
  • les stratégies sont longtemps restées basées sur des paliers (versions pour smartphone, tablette, écran) — exemple)
  • De plus en plus de largeurs différentes ⇒ les paliers ne marchent plus aussi bien : design mal optimisé pour les tailles entre deux paliers
  • Un vrai design adaptatif n'utilise pas de paliers fixés, mais des paliers qui dépendent du contenu
  • … ou pour aller encore plus loin, idéalement chaque « morceau » de la page fonctionne indépendamment du reste, et a donc ses paliers spécifiques
  • Au passage, si votre mise en page est basée sur des em (ou des rem), ce qui est conseillé, alors il faut aussi utiliser des em dans les media queries ! Encore une fois, on veut adapter le contenu à l'espace disponible, pas au type d'appareil.
  • attention cependant, em et rem ont le même effet dans les media queries (leur taille en pixel ne dépend que de la taille de police fixée par le navigateur, pas celle du CSS)…

Conclusion

  • Responsive design : design qui s'adapte
  • Design bien fait = adaptabilité de base ! exemple: design avec des tableaux. NB: si HTML propre, garantit la possibilité d'accès minimal depuis n'importe quoi. à part les images ou les tableaux, le HTML pur est très responsive !
  • Attention aux frameworks qui permettent de faire du responsive, comme Bootstrap ou Foundation :