Réflexions sur le Viewport

Ce billet date de plusieurs années, ses informations peuvent être devenues obsolètes.

Le terme viewport (contraction de [view]able [port]ion) devrait être facile à comprendre.

Il était déjà utilisé dans les spécifications CSS pour désigner une zone de visualisation avant l'avènement du web mobile.

Il est revenu sur le devant de la scène en 2007 avec la sortie de l'iPhone pour désigner un concept différent, modifiable via une balise meta viewport pas vraiment documentée mais adoptée par l'industrie.

Sous l'impulsion d'Opera, le W3C planche sur un nouveau module, CSS Device Adaptation, afin de documenter et de standardiser les mécanismes d'adaptation.

Pourtant, il est difficile d'obtenir une définition précise du mot viewport, probablement à cause de son contenu plurivoque.

Viewport et bloc conteneur initial en CSS2.1

Le mot viewport (zone de visualisation) est mentionné dans la spécification CSS2.1 conjointement avec les termes initial containing block (bloc conteneur initial) et canvas (canevas) :

User agents for continuous media generally offer users a viewport (a window or other viewing area on the screen) through which users consult a document. User agents may change the document's layout when the viewport is resized (see the initial containing block).

When the viewport is smaller than the area of the canvas on which the document is rendered, the user agent should offer a scrolling mechanism. There is at most one viewport per canvas, but user agents may render to more than one canvas (i.e., provide different views of the same document).

On comprend qu'il existe une relation entre la zone de visualisation et le bloc conteneur initial détaillée plus loin dans la spécification CSS2.1 (peaufinée au fil du temps) :

The containing block in which the root element lives is a rectangle called the initial containing block. For continuous media, it has the dimensions of the viewport and is anchored at the canvas origin;

Pour comprendre ça, je me représente les blocs conteneurs non pas comme pas des boîtes au sens CSS mais comme des rectangles "imaginaires" qui servent à positionner des éléments. Le bloc conteneur initial est un cas spécial car, sous un navigateur de bureau, sa taille est égale à la taille de la zone de visualisation (viewport) et il peut donc être redimensionné en modifiant la taille de la fenêtre du navigateur.

Ceci est formulé de manière différente dans le Web Education Community Group Wiki du W3C :

If an absolutely positioned element has no positioned ancestor, then the containing block is something called the “initial containing block,” which in practice equates to the html element. If you are looking at the web page on screen, this means the browser window;

Comparer le bloc conteneur initial à l'élément html est peut-être malheureux car cela sème la confusion en laissant penser que la boîte CSS générée pour l'élément html a la hauteur du viewport alors que la hauteur (par défaut) de la boîte (au sens CSS) dépend de son contenu.

Viewport et bloc conteneur initial en CSS3

Le module CSS basic box model (Working Draft) des spécifications CSS de niveau 3 est encore incomplet à l'heure où j'écris ces lignes :

[Define viewport and canvas]

Dans CSS Values and Units Module Level 3, les unités relatives au viewport sont relatives à la taille du bloc conteneur initial :

The viewport-percentage lengths are relative to the size of the initial containing block

Le module CSS Device Adaptation (Working Draft) rappelle le lien entre viewport et initial containing block dès le commencement :

This specification provides a way for an author to specify, in CSS, the size, zoom factor, and orientation of the viewport that is used as the base for the initial containing block.

Puis continue en faisant la distinction entre initial viewport et actual viewport :

This specification introduces a way of overriding the size of the viewport provided by the user agent (UA). Because of this, we need to introduce the difference between the initial viewport and the actual viewport.

On note ici que ce module donne à la future règle @viewport la possibilité de définir pour le bloc conteneur initial des dimensions différentes de celles du viewport.

Mais on constate qu'il n'y a pas vraiment de définition claire et précise du mot viewport dans un contexte de navigateur mobile.

Le CSSWG semble en être conscient :

There was support for his thoughts about clarifying the meaning of "viewport" when a spec isn't specific, especially for the older specs.

De plus on finit par s'emmêler les pinceaux entre viewport et initial containing block. Quid de la différence ?

Le viewport en dehors des spécifications

Dans Supporting Different Screens in Web Apps Google parle de zone rectangulaire (rectangular area) et de nombre de pixels CSS :

The viewport is the rectangular area that provides a drawable region for your web page. [The view port width defines the number of CSS pixels available].

Dans Configure the Viewport, la définition est plus générique :

A viewport controls how a webpage is displayed on a mobile device.

Dans What Is the Viewport?, Apple commence par parler d'échelle (scale) :

Safari on iOS displays webpages at a scale that works for most web content originally designed for the desktop. If these default settings don’t work for your webpages, it is highly recommended that you change the settings by configuring the viewport.

Puis précise que le terme viewport désigne des concepts légèrement différents en fonction de la version de Safari utilisée (bureau ou iOS) et qu'il est possible pour le viewport d'un mobile d'être plus grand ou plus petit que la partie visible de l'écran :

For Safari on iOS, the viewport is the area that determines how content is laid out and where text wraps on the webpage. The viewport can be larger or smaller than the visible area.

Le concept devient plus confus, et c'est peut-être ce qui pousse Peter-Paul Koch à faire la distinction entre 3 concepts différents (autour du même mot !) :

  • the visual viewport, la partie de la page actuellement visible sur l'écran (pouvant être mesurée via window.innerWidth/Height)
  • the layout viewport, l'ensemble de la page avec les parties potentiellement non visibles (pouvant être mesurée via document.documentElement.clientWidth/Height) dont la taille peut être modifiée via la balise meta viewport
  • the ideal viewport, représente la taille idéale d'une page web sur un terminal mobile (obtenue via la balise meta viewport avec width=device-width et initial-scale=1)

Si le viewport (viewable portion) peut également désigner des parties non visibles, il y a peut-être un problème de terminologie ?

La balise meta viewport

Dans les Mobile Web Application Best Practices, on peut lire à propos du meta viewport :

The viewport meta tag tells the device at what scale to render the page.

Apple nous donne sa définition :

Changes the logical window size used when displaying a page on iOS.

Pour le WHATWG, le meta viewport :

Provides a way for documents to specify (using markup rather than CSS) the size, zoom factor, and orientation of the viewport that is used as the base for the document's initial containing block.

Pour le W3C :

[…] an HTML META tag has been introduced for allowing an author to specify the size of the initial containing block, and the initial zoom factor directly.

Bloc conteneur initial sous iOS

Si on prend pour base le test de David Baron sans Media Queries mais en ajoutant simplement une balise <meta name="viewport" content="width=device-width"> on obtient ce résultat (iPhone 5s / iOS 8.1) :

Bloc conteneur initial sous iOS

Même si on considère qu'il y a 2 viewports sur les mobiles (visual viewport et layout viewport), les éléments positionnés en absolu ne sont ici alignés ni sur l'un, ni sur l'autre. C'est peut-être un bug. Comment est calculé le bloc conteneur initial dans ce cas de figure ?

La façon de déterminer le bloc conteneur initial semble aussi être à l'origine des problèmes avec background-attachment: fixed; et position: fixed; sur mobile. Voir aussi les problèmes des éléments fixes ayant un parent sur lequel un transform: translate() est appliqué.

Au passage à propos de background-attachment, la spécification parle tantôt de viewport :

The background is fixed with regard to the viewport.

Et tantôt d'initial containing block :

If the ‘background-attachment’ value for this image is ‘fixed’, then this property has no effect: in this case the background positioning area is the initial containing block [CSS21].

À propos de la position fixe, la spécification parle de viewport et pas d'initial containing block :

Fixed positioning is a subcategory of absolute positioning. The only difference is that for a fixed positioned box, the containing block is established by the viewport.

Évolution de la balise meta viewport

Apple continue de faire évoluer la balise meta viewport avec la propriété minimal-ui (sic) :

A property, minimal-ui, has been added for the viewport meta tag key that allows minimizing the top and bottom bars on the iPhone as the page loads.

Microsoft a décidé de ne pas tenir compte de la balise meta viewport dans Internet Explorer 10 en mode Metro lorsque l'on est en Snap Mode ou Snapped View pour tout viewport dont la largeur est inférieure à 400px. Pour avoir un résultat correct dans ce cas de figure il faudra passer par du préfixe vendeur et utiliser @-ms-viewport et sa propriété width qui :

Indicates the preferred viewport width used in determining the size of the initial containing block.

Pour conclure

En vrac et à ce stade de la réflexion :

  • la différence entre viewport et bloc conteneur initial dans les spécifications CSS n'est pas du tout évidente (si tant est qu'il y en ait une ?)
  • si on parvient à utiliser la balise meta viewport dans la pratique, il est plus difficile d'en donner une définition précise
  • le nom de la balise meta viewport est-il vraiment bien choisi ?
  • distinguer plusieurs types de viewports complique les choses à mon sens (naming things)
  • employer viewport (viewable portion) pour (potentiellement) désigner des parties non visibles semble contradictoire avec le sens même du mot viewport

Avant Pixel de référence CSS Après Django et le pouvoir du Q

Tag Kemar Joint