Tutoriel vidéo HTML-CSS : Ecran Retina

A propos

Apple a mis sur le marché de nouveaux périphériques équipés d'écran "Retina" qui ont la spécificité d'avoir une densité de pixels 2 fois plus grande que les écrans standards. De plus en plus d'application Mac s'adaptent à cette nouvelle densité mais quand est-il du Web ? 

Reti..quoi ?

Avant de vouloir aller plus loin il est important de comprendre ce que représente ces écrans Retina. Derrière ce nom commercial se cache un principe plutôt simple. Pour afficher une page web de 1024 pixels de largeur l'écran retina n'utilisera pas 1024 pixels physique mais 2048 pixels physiques (petit points sur l'écran). Du coup ce nouveau format d'écran n'impacte pas vos valeurs CSS (1px en CSS aura la même "taille" que l'on soit sur un écran retina/non-retina) mais affecte grandement le rendu des images. En effet jusqu'à maintenant on ne se souciait pas trop de la densité de pixels l'écran utilisait 1 pixel physique  pour rendre 1 pixel de notre image.

Une image

Sur un écran retina ce n'est plus le cas et du coup le moteur de rendu va dupliquer les pixels pour agrandir l'image sur sa nouvelle densité, ce qui donne une image un peu "flou". Ce défaut est très visible sur des formes bien délimitées (comme des logos par exemple).

Comment on corrige ce problème ?

La solution est plutôt simple, en théorie tout du moins, il suffit tout simplement de distribuer des images 2 fois plus grandes pour des écrans Retina (on utilisera le suffix @2x par convention). Par exemple pour afficher une image de 200x200 on créera une image de 400x400 et en HTML on écrira

<img src="img@2x.png" width="200" height="200">

Le problème ici c'est qu'un utilisateur avec un écran standard va devoir charger une image 2 fois plus grande pour rien et qui risque, en plus, de perdre en qualité avec le redimensionnement.

Une <image> 2 fois plus grande

Une solution est alors de mettre l'image standard et de la remplacer par l'image grande taille en javascript en détectant la densité de l'écran avec la nouvelle propriété window.devicePixelRatio

<img src="img.png" width="200" height="200" class="retina"> 

 <script type="text/javascript">
   (function($){
     
     if(window.devicePixelRatio > 1.5){
       $('.retina').each(function(){
         var img = $(this);
         img.attr('src', img.attr('src').replace('.','@2x.')); 
       })
     }

   })(jQuery);
 </script>
 
 

Cette solution a l'avantage d'être simple à mettre en place mais elle ne fonctionneme pas sur Firefox et Internet Explorer qui ne comprendront pas window.devicePixelRatio (undefined)

En utilisant CSS et Media Queries

La plupart des navigateurs modernes ont intégré les media queries concernant les ratio de pixel, du coup on peut utiliser le CSS pour délivrer des images "retina" pour des écrans ayant une densité de pixel supérieure :

.madiv {
   background-image: url(img.png);
   background-size: 200px 300px;
   height: 300px;
   width: 200px;
 }

 @media only screen and (-Webkit-min-device-pixel-ratio: 1.5),
 only screen and (-moz-min-device-pixel-ratio: 1.5),
 only screen and (-o-min-device-pixel-ratio: 3/2),
 only screen and (min-device-pixel-ratio: 1.5) {
   .madiv {
     background-image: url(img@2x.png);
   }
 } 

Cette méthode permet de remplacer les éléments graphiques utilisés pour le design de votre page Web. L'avantage est qu'elle est supportée par tous les navigateur et permet d'avoir un contrôle précis du rendu. En revanche cela peut représenter un travail plus ou moins conséquent suivant le nombre d'images utilisées sur votre site.

SVG Scalable Vector Graphics

Les images au format SVG sont des images vectorielles basées sur le format XML. Elles sont supportés sur tous les navigateurs modernes et ne sont pas affectées par la densité de pixel car ce sont des images vectorielles (basées sur des formes géométriques, et non pas sur des pixels). Il est donc possible de les redimensionner à l'infinie sans avoir de perte de qualité.

Alors pourquoi ne pas utiliser ce format là me direz vous ? Il y a 2 raisons à cela. La première c'est les limitations de ce format d'image. Les images vectorielles sont caractérisées par des formes géométrique, on ne peut donc pas avoir de photo en SVG par exemple. En revanche ça sera un bon choix de format si votre image a été créé sur Adobe Illustrator ou Inkscape. L'autre problème est un problème de compatibilité. Il faut prévoir une image de secours pour les navigateur ne supportant pas le SVG (on peut détecter le support de ce format avec modernizr

$(document).ready(function(){
  if(!Modernizr.svg) {
    $("img[src$='.svg']).each(function(i) {
      $(this).attr('src', $(this).attr('src').replace('.svg','.png'));
    });
  }
});

Icons en police

Une autre solution pour ne pas souffrir de cette différence de densité est d'utiliser des icônes vectorielles sous forme de police. Cette méthode se démocratise de plus en plus et consistre à utiliser @font-face pour mettre en place une police qui utilise des icônes à la place des caractères standards. Des packs de polices sont facilement trouvable sur Internet comme par exemple : IconicFontello ...

Cette méthode à l'avantage d'être supportée par quasiment tous les navigateurs, mais reste limitée à des icônes monochromatiques. 

Conclusion

La technologie Retina est relativement nouvelle et pour le moment les moyen de gérer cette nouvelle densité de pixels ressemble plus à des hack qu'à de vrai solution. Il ne reste plus qu'à attendre qu'une convention se standardise pour donner une solution "béton" pour gérer cette nouvelle résolution. En attendant à vous de choisir/combiner ces méthodes suivant les cas pour obtenir le meilleur support possible.