Web

Comprendre le Viewport dans le Web mobile

Article par (Intégrateur du Dimanche, Strasbourg)
Créé le , mis à jour le (126071 lectures)
Tags : meta, orientation, viewport, mobile, webmobile, responsive, device-width, initial-scale, portrait, paysage

Le Viewport désigne schématiquement la surface de la fenêtre du navigateur. Cependant, la notion de viewport sur un appareil mobile est différente de celle sur un écran de bureau : sur mobile, le navigateur ne dispose pas de "fenêtre" réelle, ni de barres de défilement car tout est prévu pour naviguer de manière tactile.

Comprendre la notion de viewport est absolument indispensable dans un projet d'intégration de site web pour tablettes et smartphones, ou dans un esprit d'adaptation "Responsive Web Design".

Les différentes surfaces d'un mobile

Afin de mieux cerner et exploiter le concept de viewport sur terminaux nomades, il nous faut commencer par maîtriser deux notions de base : la surface réelle et la surface en "pixels CSS" des mobiles.

mobile widthLa surface réelle

C'est le nombre physique de pixels qui composent la matrice de l'écran, telle que le constructeur le décrit dans les caractéristiques, en gros la "résolution" (en vérité le terme juste est "définition").

Par exemple, la surface réelle de quelques terminaux Apple :

  • 320x480px pour l'iPhone 3
  • 640x960px pour l'iPhone 4
  • 640x1136px pour l'iPhone 5
  • 768x1024px pour l'iPad 2
  • 1536x2048px pour l'iPad 3

La surface en "pixels CSS"

Egalement appelée device-width (device-height) ou screen.width (screen.height) ou encore "ça dépend", il s'agit du nombre de pixels virtuels que le terminal pense avoir et sur lequel il fonde son affichage.
Le hic est que cette surface ne correspond pas toujours à la surface réelle, notamment pour les mobiles dits "retina" ou haute définition. Un "pixel CSS" n'est donc pas égal à un pixel physique.

Par exemple, la surface device-width et device-height en "pixels CSS" (ou "pixels indépendants" DIP) de quelques terminaux Apple (pour ne citer qu'eux) :

  • 320x480px pour l'iPhone 3
  • 320x480px pour l'iPhone 4
  • 320x568px pour l'iPhone 5
  • 768x1024px pour l'iPad 2
  • 768x1024px pour l'iPad 3

Vous vous doutez bien qu'il en est de même pour un grand nombre d'autres terminaux, toutes marques confondues. Pour avoir un panel de périphériques plus important, je vous invite à découvrir http://mydevice.io/devices/ ou encore http://screensiz.es

Attention, les terminaux Apple ont une particularité que n'ont pas les autres mobiles : la valeur de device-width est invariable en portrait et en paysage. Le device-width d'un iPad vaudra toujours 768px quelle que soit l'orientation. Plus de détails dans la partie "Portrait et Paysage" ci-dessous...

iphone device-width

Viewport : les mobiles mentent !

Suite à cette introduction aux différentes tailles des mobiles particulièrement déroutante, je vous suggère de continuer à vous accrocher… parce que la notion de viewport est loin d'être une évidence non-plus !

Pour débuter en douceur, apprenez que par défaut la taille du viewport d'un terminal mobile ne correspond ni à la taille de son écran réelle ni celle en "pixels CSS".
Elle est généralement bien supérieure à la surface physique, afin de pouvoir y caler n'importe quelle page web en lui affectant un niveau de (dé)zoom.

Autre surprise, la valeur initiale du viewport ne dépend pas du terminal, comme on pourrait le supposer, mais... du navigateur mobile (et peut parfois même être modifiable par l'utilisateur dans ses réglages).

Voici quelques valeurs par défaut :

  • Android 1, 2 et 3 : 800px
  • Android 4 : 980px
  • Opera mini : 850px
  • Opera mobile : 980px
  • Safari mobile : 980px
  • Internet Explorer mobile : 1024px

Niveau de zoom initial

Compte tenu de ces différentes surfaces, les pages web s'affichent par défaut de manière à ce que toute la surface entre dans celle de l'écran.

Ce niveau de zoom initial correspond à une simple division mathématique de device-width / viewport.

Au final, la surface réelle en pixel n'est pas prise en compte dans le calcul du niveau de zoom d'affichage.

Par exemple, Safari mobile sur iPhone 4 va afficher par défaut les pages web dans une fenêtre de 980px de large au sein des 320px de largeur qu'il croit avoir… bien qu'il en ait physiquement 640px. Le niveau de zoom initial sera de 320 / 980, soit environ 0.326x.

Illustration : site de orange.fr vu par un mobile (opera)

opera mobile viewport

La balise meta viewport

Fort heureusement, pour s'affranchir de ce zoom intempestif rendant les contenus illisibles, il est possible de modifier et d'imposer la taille de la surface du viewport d'un périphérique mobile. Non pas en CSS comme on pourrait le croire, mais en... HTML, à l'aide d'un élément <meta> proposé initialement par Apple.

Les différentes valeurs de cet élément meta et de son attribut content, offrent la possibilité de fixer la largeur de viewport à la valeur souhaitée, voire de l'adapter automatiquement à la valeur de device-width du terminal.

Illustration : viewport par défaut sur mobile

Observation : la page entre dans une surface par défaut de 850 pixels de large et l'image de 640px occupe environ 2/3 de la surface.

viewport1

Illustration : viewport défini à width=640px

Observation : la surface de la fenêtre est à présent parfaitement adaptée à l'image de 640 pixels de large, mais le contenu demeure trop petit.

viewport2

Code HTML correspondant :

<meta name="viewport" content="width=640">

Illustration : viewport défini à width=320px

Observation : la surface de la fenêtre est définie à 320px de large, mais demeure flexible : les éléments plus larges étirent le viewport.

viewport3

Code HTML correspondant :

<meta name="viewport" content="width=320">

Illustration : viewport défini à width=device-width

Observation : la valeur de device-width du terminal et d'Opera mobile étant de 320px, la surface de la fenêtre est définie à 320px de large comme précédemment, et les éléments plus larges étirent le viewport.

viewport4

Code HTML correspondant :

<meta name="viewport" content="width=device-width">

Comme on peut le constater à travers ces divers exemples, définir une taille de viewport est souvent loin d'être suffisant, même s'il s'agit d'une première étape. Vous aurez ensuite besoin d'une méthodologie d'adaptation de l'ensemble de vos élements de contenus et de structure.

Le niveau de zoom (scale)

Comme nous l'avons observé, les pages web sont dézoomées par défaut pour entrer dans la surface device-width du terminal.

Ce zoom initial correspond à un ratio dont la valeur est inférieure à 1. Il nous est cependant parfaitement possible de modifier cette valeur par défaut à l'aide de la fonction initial-scale et de la remplacer par celle qui nous convient, plutôt que d'imposer une largeur de viewport.

Illustration : zoom initial défini à 1.0

Observation : le zoom initial est fixé à 1.0. Le viewport s'adapte de telle façon qu'un "pixel CSS" corresponde à un pixel réel. En clair, sa surface passe à 320x480px, c'est à dire les valeurs de device-width  et device-height du terminal. La fenêtre n'est pas étirable, et les éléments plus larges débordent du viewport et sont masqués.

viewport5

Code HTML correspondant :

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

Illustration : zoom initial défini à 0.5

Observation : cette fois, le zoom initial est fixé à 0.5. Le viewport correspond à une surface de 640x960 pixels, parfait  pour notre image, mais un peu aléatoire dans un vrai projet web.

viewport6

Code HTML correspondant :

<meta name="viewport" content="initial-scale=0.5">

Pour conclure sur cette présentation de l'élément HTML <meta> viewport, retenez qu'il est possible de fixer la taille de la surface de l'écran au pixel près ou de manière adaptative (device-width) à l'aide de la propriété width, mais aussi de jouer sur un autre levier, celui du zoom initial avec initial-scale... ou de cumuler les deux si tel est votre besoin.

Autres valeurs de la balise meta viewport

La balise <meta> autorise d'autres valeurs utilisables dans vos projets :

  • width
      largeur de fenêtre viewport (par exemple width="device-width")
  • height
      hauteur de fenêtre viewport (par exemple height="device-height")
  • initial-scale
      niveau de zoom initial (par exemple initial-scale="1.0")
  • minimum-scale
      niveau de zoom minimal (par exemple minimum-scale="0.5")
  • maximum-scale
      niveau de zoom maximal (par exemple maximum-scale="3.0"). Attention, la valeur "1.0" interdit le zoom et peut rendre vos pages inaccessibles
  • user-scalable
      possibilité à l'utilisateur de zoomer (par exemple user-scalable="yes"). Attention, la valeur "no" interdit le zoom et peut rendre vos pages inaccessibles
  • target-densitydpi
      choix de résolution, en dpi, de l'affichage général (spécifique Webkit et semble avoir été abandonné)

Bugs de zoom au format paysage

La détection de l'orientation du périphérique se fait de manière native par le navigateur mobile.

Selon vos choix de valeurs de la balise <meta> viewport, des différences d'affichage peuvent survenir entre le format vertical (portrait) et horizontal (paysage).

En effet, sur certains terminaux (notamment Apple), en fixant une surface de viewport à width="device-width" (pratique très courante), vous allez également conserver cette valeur lors du passage en orientation paysage alors que la valeur souhaitée serait plutôt device-height dans ce sens.

Il en résultera une adaptation automatique du contenu et celui-ci sera agrandi d'environ 1/3 à plus selon les terminaux.

En définitive, il semble que la valeur la plus robuste pour l'ensemble des périphériques soit une addition de "width" et de "initial-scale" :

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

Illustration : width=device-width sur iPhone 5 en portrait et paysage

Observation : les valeurs device-width et device-height de l'iPhone 5 sont respectivement de 320px et 568px. En fixant une valeur de width=device-width,  le viewport en orientation paysage fait 320px (device-width) dans une surface de 568px (device-height), soit un rapport de zoom global de page de +44% en paysage !

iphone5 device-width

iphone5 device-width landscape

Illustration : initial-scale=1.0 sur iPhone 5 en portrait et paysage

Observation : en définissant un niveau de zoom initial à 1, la surface du viewport correspond exactement aux valeurs device-width et device-height de l'iPhone 5 soit respectivement de 320px et 568px. La largeur et la hauteur du viewport n'étant pas fixés via la propriété width, celui-ci s'adapte automatiquement à la largeur offerte par le terminal, c'est à dire 320px en portrait et 568px en paysage. L'effet de zoom disgrâcieux est donc estompé.

iphone5 initial-scale

iphone5 initial-scale landscape

Pour en savoir plus sur ce sujet épineux d'orientation et de bugs d'affichage, je vous invite à parcourir la ressource suivante : "Adieu width=device-width ?".

Du côté des spécifications : @viewport

En y repensant, j'ai oublié de préciser un détail important en ce qui concerne la balise HTML <meta> viewport, mais vous l'aurez peut-être deviné par vous-même : il se trouve que cet élément, inventé par Apple, est bien entendu complètement propriétaire et étranger à toute spécification homologuée.
Fort heureusement, la grande majorité des navigateurs mobiles l'ont adopté en vertu de ses bénéfices pour l'intégrateur.

Sachez que le W3C intègre cette fonctionnalité au sein de son équivalent standard, sous forme d'une règle-at en CSS, ce qui semble ma foi plus logique : @viewport.

Cette règle-at est actuellement déjà implémentée sur Opera mobile, IE10 mobile et Firefox mobile, et se présente sous la forme suivante :

@viewport {
   width: device-width; /* largeur du viewport */
   zoom: 1; /* zoom initial à 1.0 (et clin d'oeil aux fans d'IE6/7) */
}

Lorsque cette fonctionnalité standard sera implémentée plus massivement (notamment sur Safari mobile et Android), il sera temps de tourner la page et de laisser de côté nos chères balises <meta> viewport. Mais c'est encore quelque peu prématuré...

Conclusion et ressources

Au vu de ce (long) article, vous aurez compris que le Web mobile demeure encore parfois difficile à saisir et que bon nombre de ses particularités restent encore obscures.

J'espère que toutes ces explications et exemples visuels vous auront permis de mieux comprendre le concept général du viewport sur les mobiles et de mettre en oeuvre vos propres solutions pour le dompter.

Quelques ressources très utiles pour finir :

Commentaires

_laurent a dit le

Superbe d'avoir réuni et clarifié toute ces infos !! Merci !

Olivier C a dit le

Super, merci beaucoup,
Codant le responsive en aveugle car n'ayant pas de mobile (je suis amateur, je précise) j'ai toujours un peu du mal avec l'application concrète de ces notions...

marc.suisse a dit le

Merci beaucoup d'avoir pris le temps de rédiger cet article !!

Skoua a dit le

Toute petite erreur : la surface réelle de l'iPhone 4 est de 640x960px et pas 480x960px.

Merci pour l'article, ça clarifie pas mal de choses.

Raphael a dit le

@Skoua : Ah oui merci, c'est corrigé.

Olivier C a dit le

"Ah oui merci, c'est corrigé."
Et... ces 640px de large ne seraient-ils pas aussi valable pour l'iPhone5 ? ;-)

Raphael a dit le

@Olivier C : oui je l'ai corrigé dans la foulée

pijahema a dit le

C'est quand même assez tordu dans l'ensemble :-)

yahyaba a dit le

Le web a bien changé entre temps pour un vieux "webmaster" (avant 2005) comme moi !

ironman a dit le

j'essaye de faire systématiquement maintenant un site RWD (ce qui n'était pas le cas avant), et c'est vrai que c'est un vrai case-tête !! La solution parfaite n'existe pas, entre les différents navigateurs, smartphones... le tout est d'être le plus proche possible d'une solution agréable et fonctionnelle.

7h47 a dit le

Donc, est-ce qu'on peut donc résumer est disant que pour commencer on utilise ces valeurs :
<meta name="viewport" content="width=device-width">
<meta name="viewport" content="initial-scale=1.0">

Alexandrechapelle a dit le

Bonjour,
Beaucoup d'images du tutoriel ont disparu, pourriez vous les remettre en ligne ?
Merci

Alexandrechapelle a dit le

Bonjour,
Beaucoup d'images du tutoriel ont disparu, pourriez vous les remettre en ligne ?
Merci

Alexandrechapelle a dit le

Super les images sont de retour merci !

eviouchka a dit le

Merci beaucoup Raphaël pour toutes ces explications , c'est beaucoup plus clair mais ça reste complexe tout de même... mais si j'ai bien compris, on essaie de "jouer" entre les valeurs device-width et device-height et le initial-scale et selon notre template pour faire afficher correctement son site sur la plupart des mobiles, sachant que ce l'on ne peut maîtriser l'affichage à 100% sur tous les terminaux et dans toutes les positions (portrait, paysage ) ?
et quand tu parles de "mettre en oeuvre vos propres solutions pour le dompter" , tu parles des valeurs ci-dessus associées aux media-queries en CSS ?

eviouchka a dit le

merci pour les liens "ressources utiles" en supplément ;
si j'ai bien compris ce qui est noté dans cette page -> http://developer.android.com/guide/webapps/ta...
content="target-densitydpi=device-dpi compris dans la balise
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width" /> ne s'adresse qu'au moteur Android ?