WebView au pixel près

Publié le 28 février 2014

Vous pouvez utiliser un certain nombre d'options pour créer l'interface parfaite pour votre WebView.

Définir la balise Meta viewport

La balise méta de vue d'ensemble est l'une des balises les plus importantes à ajouter à votre application Web. Sans elle, la WebView peut se comporter comme si votre site était conçu pour les navigateurs pour ordinateur. Votre page Web est alors dotée d'une largeur plus importante (généralement 980 px) et est redimensionnée pour s'adapter à la largeur de la WebView. Dans la plupart des cas, cela se traduit par une version miniature de la page qui nécessite que l'utilisateur fasse un panoramique et un zoom pour lire le contenu.

Si vous souhaitez que la largeur de votre site corresponde à 100% de la largeur de la WebView, définissez la balise meta de la fenêtre d'affichage:

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

Définissez la largeur sur la valeur spéciale "device-width" pour mieux contrôler la mise en page de la page.

Par défaut, la WebView définit la fenêtre d'affichage sur "device-width", plutôt que sur une fenêtre d'affichage pour ordinateur de bureau. Toutefois, pour un comportement fiable et contrôlé, il est recommandé d'inclure la balise méta de vue.

Afficher les sites pour ordinateur

Dans certains cas, vous devrez peut-être afficher du contenu qui n'est pas conçu pour les appareils mobiles. Par exemple, vous pouvez afficher des contenus que vous ne contrôlez pas. Dans ce cas, vous pouvez forcer la WebView à utiliser un viewport de taille d'ordinateur:

Si ces méthodes ne sont pas définies et qu'aucune fenêtre d'affichage n'est spécifiée, la WebView tente de définir la largeur de la fenêtre d'affichage en fonction de la taille du contenu.

En outre, vous pouvez utiliser l'algorithme de mise en page TEXT_AUTOSIZING, qui augmente la taille de la police pour la rendre plus lisible sur un appareil mobile. Consultez setLayoutAlgorithm.

Utiliser le responsive design

Le responsive design est une approche de conception d'interface qui change en fonction de la taille de l'écran.

Il existe plusieurs façons d'implémenter le responsive design. L'une des plus courantes est les requêtes @media, qui appliquent le CSS aux éléments en fonction des caractéristiques d'un appareil.

Par exemple, supposons que vous souhaitiez passer d'une mise en page verticale à une mise en page horizontale en fonction de l'orientation. Définissez les propriétés CSS sur portrait par défaut:

.page-container {
    display: -webkit-box;
    display: flex;

    -webkit-box-orient: vertical;
    flex-direction: column;

    padding: 20px;
    box-sizing: border-box;
}

Pour passer à une mise en page horizontale, définissez la propriété flex-direction en fonction de l'orientation:

@media screen and (orientation: landscape) {
  .page-container.notification-opened {
    -webkit-box-orient: horizontal;
    flex-direction: row;
  }

  .page-container.notification-opened > .notification-arrow {
    margin-right: 20px;
  }
}

Vous pouvez également modifier la mise en page en fonction de la largeur de l'écran.

Par exemple, ajuster la taille de la largeur du bouton de 100% à une valeur inférieure à mesure que la taille de l'écran physique augmente.

button {
  display: block;
  width: 100%;
  ...
}

@media screen and (min-width: 500px) {
  button {
    width: 60%;
  }
}

@media screen and (min-width: 750px) {
  button {
    width: 40%;
    max-width: 400px;
  }
}

Il s'agit de modifications mineures, mais selon votre UI, les requêtes multimédias peuvent vous aider à apporter des modifications beaucoup plus importantes à l'apparence de votre application, tout en conservant le même code HTML.

Images nettes et claires

La variété des tailles et densités d'écran pose également des défis pour les images. Les images plus petites nécessitent moins de mémoire et se chargent plus rapidement, mais elles sont floues si vous les agrandissez.

Voici quelques conseils pour vous assurer que vos images sont nettes et claires sur n'importe quel écran:

  • Utilisez le CSS pour les effets évolutifs.
  • Utilisez des graphiques vectoriels.
  • Fournissez des photos en haute résolution.

Utiliser le CSS pour des effets évolutifs

Utilisez le CSS autant que possible au lieu d'images. Il est possible que certaines combinaisons de propriétés CSS soient coûteuses à afficher. Testez toujours les combinaisons spécifiques que vous utilisez.

En savoir plus sur le First Contentful Paint (FCP), qui mesure le temps écoulé entre le moment où l'utilisateur a accédé à la page pour la première fois et l'affichage à l'écran d'une partie du contenu de la page. "Contenu" désigne le texte, les images (y compris les images de fond), les éléments <svg> et les éléments <canvas> non blancs.

Utiliser des graphiques vectoriels

Les Scalable Vector Graphics (SVG) sont un excellent moyen de fournir une image évolutive. Pour les images adaptées aux graphiques vectoriels, le format SVG fournit des images de haute qualité avec des tailles de fichiers très petites.

Fournir des photos haute résolution

Utilisez une photo adaptée à un appareil haute résolution et mettez l'image à l'échelle à l'aide du CSS. De cette façon, l'image peut s'afficher en haute qualité sur tous les appareils. Si vous utilisez une compression élevée (paramètre de qualité faible) lors de la génération de l'image, vous pouvez obtenir de bons résultats visuels avec une taille de fichier raisonnable.

Cette approche présente quelques inconvénients potentiels: les images fortement compressées peuvent présenter des artefacts visuels. Vous devez donc effectuer des tests pour déterminer le niveau de compression que vous jugez acceptable. Redimensionner l'image en CSS peut être une opération coûteuse.

Si une compression élevée ne répond pas à vos besoins, essayez le format WebP, qui offre une image de haute qualité avec une taille de fichier relativement faible. N'oubliez pas de fournir un élément de remplacement pour les versions d'Android où WebP n'est pas pris en charge.

Contrôle ultraprécis

Dans de nombreux cas, vous ne pouvez pas utiliser une seule image pour tous les appareils. Dans ce cas, vous pouvez sélectionner différentes images en fonction de la taille et de la densité de l'écran. Utilisez des requêtes multimédias pour sélectionner des images de fond en fonction de la taille et de la densité de l'écran.

Vous pouvez utiliser JavaScript pour contrôler le chargement des images, mais cela ajoute de la complexité.

Requêtes multimédias et densité d'écran

Pour sélectionner une image en fonction de la densité de l'écran, vous devez utiliser des unités dpi ou dppx dans votre requête multimédia. L'unité dpi représente les points par pouce CSS, et dppx les points par pixel CSS.

Le tableau suivant illustre la relation entre dpi et dppx.

Rapport de pixels de l'appareil Densité d'écran généralisée Points par pouce CSS (dpi) Points par pixel CSS (dppx)
x 1 MDPI 96dpi 1dppx
x 1,5 HDPI 144dpi 1,5dppx
2 XHDPI 192dpi 2dppx

Les buckets de densité d'écran généralisés sont définis par Android et sont utilisés ailleurs pour exprimer la densité d'écran (par exemple, https://screensiz.es).

Image de fond

Vous pouvez utiliser des requêtes multimédias pour attribuer des images de fond à des éléments. Par exemple, si vous avez une image de logo de 256 x 256 pixels sur un appareil dont le format en pixels est de 1,0, vous pouvez utiliser les règles CSS suivantes:

.welcome-header > h1 {
  flex: 1;

  width: 100%;

  max-height: 256px;
  max-width: 256px;

  background-image: url('../images/html5_256x256.png');
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

Pour remplacer cette image par une image plus grande sur les appareils avec un format de pixel de 1,5 (hdpi) et 2,0 (xhdpi), vous pouvez ajouter les règles suivantes:

@media screen and (min-resolution: 1.5dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_384x384.png');
  }
}

@media screen and (min-resolution: 2dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_512x512.png');
  }
}

Vous pouvez ensuite fusionner cette technique avec d'autres requêtes multimédias, telles que min-width, ce qui est utile lorsque vous tenez compte de différents facteurs de forme.

@media screen and (min-resolution: 2dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_512x512.png');
  }
}

@media screen and (min-resolution: 2dppx) and (min-width: 1000px) {
  .welcome-header > h1{
    background-image: url('../images/html5_1024x1024.png');

    max-height: 512px;
    max-width: 512px;
  }
}

Vous remarquerez peut-être que max-height et max-width sont définis sur 512 px pour la résolution 2ddpx, avec une image de 1 024 x 1 024 px. En effet, un "pixel" CSS tient compte du format de l'appareil (512 px * 2 = 1 024 px).

Qu'en est-il de <img/> ?

Le Web n'offre actuellement aucune solution à ce problème. Il existe quelques propositions, mais elles ne sont pas disponibles dans les navigateurs actuels ni dans la WebView.

En attendant, si vous générez votre DOM en JavaScript, vous pouvez créer plusieurs ressources d'image dans une structure de répertoire réfléchie:

images/
  mdpi/
    imagename.png
  hdpi/
    imagename.png
  xhdpi/
    imagename.png

Utilisez ensuite le format en pixels pour essayer d'extraire l'image la plus appropriée:

function getDensityDirectoryName() {
  if(!window.devicePixelRatio) {
    return 'mdpi';
  }

  if(window.devicePixelRatio > 1.5) {
    return 'xhdpi';
  } else if(window.devicePixelRatio > 1.0) {
    return 'hdpi';
  }

  return 'mdpi';
}

Vous pouvez également modifier l'URL de base de la page pour définir les URL relatives des images.

<!doctype html>
<html class="no-js">
<head>
  <script>
    function getDensityDirectoryName() {
      if(!window.devicePixelRatio) {
          return 'mdpi';
      }

      if(window.devicePixelRatio > 1.5) {
          return 'xhdpi';
      } else if(window.devicePixelRatio > 1.0) {
          return 'hdpi';
      }

      return 'mdpi';
    }

    var baseUrl =
        'file:///android_asset/www/img-js-diff/ratiores/'+getDensityDirectoryName()+'/';
    document.write('<base href="'+baseUrl+'">');
  </script>

    ...
</head>
<body>
    ...
</body>
</html>

Cette approche bloque le chargement de la page et force l'utilisation de chemins absolus pour toutes les ressources, telles que les images, les scripts et les fichiers CSS, car l'URL de base pointe vers un répertoire spécifique à la densité.