Image responsive, enfin une solution pérenne ?

Edition de l’article le 06/08/2012: Il existe un doute sur le choix définitif de l’élément html5, du fait de la division de la w3c en deux organismes. Je ne suis pas encore sûr à 100% de ce qui va être choisis, et ce sera peut être les deux. Voir cet article sur srcset


Après plus d’un an de discussion et d’échanges dans les communautés de développeurs, d’intégrateurs et de designers web autour de la gestion des images dans un design responsif, il semblerait qu’une solution pérenne vienne d’apparaître, notamment sur le Responsive Images Community Group

Pour re-situer la problématique (je ne peux pas tout reprendre depuis le début) nous avons besoin de servir une image appropriée au périphérique qui affiche la page web responsive, afin de limiter l’utilisation de la bande passante, mais aussi d’éviter les effet d’aliasing et les déformations que certains navigateurs appliquent aux images lorsqu’elles sont redimensionnées en html.

Différentes techniques sont apparues, toutes des hacks utilisant diverses solutions, basées sur du javascript, ( ex: http://filamentgroup.com/examples/responsive-images/) ou du php et un fichier htacess (ex:http://adaptive-images.com/ ) solution que j’ai présentée à la t3uni12. Cette dernière reste à mon sens très intéressante, y compris dans le cadre de TYPO3, pour générer les images, mais pas pour charger les images ainsi générées.

Vous trouverez aussi facilement des tonnes de solutions tordues et de hacks sortis de l’imagination de développeurs, mais qui risquent de ne plus fonctionner dans quelques temps, ou juste de ne pas fonctionner sur tous les navigateurs.

Une image par breakpoint (condition dans les media-queries)

Notre postulat de départ et donc que nous avons généré différentes images pour nos différentes versions de taille d’écran.

Il nous faut maintenant détecter quelle est la taille du site qui est délivré au périphérique, et lui servir l’image la mieux adaptée à l’affichage.

La création de cette image n’est pas au programme de cet article, mais sera abordé dans l’article « 2ème solution: Génération d’une image adaptée à la taille de l’interface avec http://adaptive-images.com/ »

Servir l’image la mieux adaptée, les enjeux

Voilà, maintenant que vous êtes bien chaud, on rentre dans le gras du sujet ! Nous avons donc disons 3 versions de notre image à des tailles différentes, prêtes dans un dossier.

Quelques questions se posent maintenant:

  1. Comment je sais quelle image je dois charger ?
  2. Comment faire pour ne pas « pré-charger » toutes les images ?
  3. Comment faire pour ne pas charger une image mal adaptée en premier ?
  4. Pourquoi est ce que je ne mettrais aucune images dans mon site ? Comme ça je n’ai pas de problèmes hein ?
  5. Je m’en moque, je ne mets qu’une seule grosse image, et ceux qui mettent trop longtemps à la charger n’ont qu’a désactiver les images.

Le point 5 est tentant, mais c’est une question de respect, et de professionnalisme, et même si mon éthique du web s’arrête là ou ie6 commence, je ne conçois pas de donner à tout le monde la même image, grand format donc. Pour passer pas mal de temps dans le métro parisien, en « EDGE », je sais ce que c’est de se trouver face à une image plein écran à charger, c’est l’horreur.
De plus il y a encore pas mal de région en France ou la connexion est en 1mb, et charger des grosses images quand ce n’est pas nécessaire est bien sûr toujours une perte de temps.
Ensuite, on oublie souvent, mais que ce soit en Anglais ou en Français, votre site va peut être attirer des lecteurs de pays en voie de développement, qui accèdent encore souvent à internet via un modem.
Enfin, dernier point, évoqué lors de ma présentation à la t3uni12, qui prends le contre-pied total des points évoqués précédemment, vous avez peut être envie de servir des images en meilleure qualité pour les écrans rétina d’apple, qui sont mieux définis que nos écrans traditionnels.

Je vais citer un ami qui vient de publier ce message sur son facebook:
Got my new Mac from the office on Tuesday. Retina display is totally awesome. And now Chrome just updated to support it :-) The only thing is that 72 dpi images now look horribly fuzzy ;-)

Ce qui se passe dans son cas est effectivement un problème puisque la quasi totalité des images sur le web n’est pas adaptée aux écrans rétina..

Servir la meilleure image, et alors on fait comment ?

La réponse la plus courante sur les forums de discussion est:

Tu as pensé à utiliser du javascript ?
Réponse: &é_’èç£*ù va te faire àç’àçé$ù* si tu crois qu’on y a pas pensé espèce de mangeur de javascript de &é$*ù
Réponse politiquement correcte: Le javascript n’est pas toujours une solution viable, tout le monde n’a pas un navigateur compatible, et ce n’est pas non plus forcément pereine sur du moyen / long terme.

Ici je vais vous présenter une méthode propre, qui prends déjà en compte les spécifications html5 à venir, et qui ne nécessite pas de plugin ou de code supplémentaire.

Sans transition, un exemple de code utilisant la solution picturefill

<picture alt="texte alternatif de mon image">
	<source srcset="small.jpg 1x, small-highres.jpg 2x"></source>
	<source media="(min-width: 400px)" srcset="medium.jpg 1x, medium-highres.jpg 2x"></source>
	<source media="(min-width: 800px)" srcset="large.jpg 1x, large-highres.jpg 2x"></source>
	<source media="(min-width: 1000px)" srcset="extralarge.jpg 1x, large-highres.jpg 2x"></source>
		<noscript>
			<img src="small.jpg" alt="texte alternatif de mon image">
		</noscript>
	<img alt="texte alternatif de mon image" src="extralarge.jpg">
</picture>

Explication du code

Le code est orienté « mobile first », il charge uniquement la petite version de l’image en premier.

<source srcset="small.jpg 1x, small-highres.jpg 2x"></source>

Ensuite, la bonne image est servie en fonction de la largeur de l’affichage en pixel, et de la densité en pixels de l’écran. (dpi ).

<source media="(min-width: 400px)" srcset="medium.jpg 1x, medium-highres.jpg 2x"></source>
	<source media="(min-width: 800px)" srcset="large.jpg 1x, large-highres.jpg 2x"></source>
	<source media="(min-width: 1000px)" srcset="extralarge.jpg 1x, large-highres.jpg 2x"></source>

On aurait pu aussi spécifier une largeur en « em », mais pour clarifier la compréhension du code, j’ai choisis des largeurs en pixels. Cependant la bonne pratique pour le responsive design est d’utiliser des « em », afin de permettre au design de réagir au zoom de navigateur.

  • Si l’élément picture n’est pas supporté, la balise < img > est affichée.
    <img alt="texte alternatif de mon image" src="extralarge.jpg">
  • Si le javascript est désactivé, on affiche la petite image ( sans la balise < noscript > le code fonctionne, mais affiche la grande image.)
    <noscript>
    			<img src="small.jpg" alt="texte alternatif de mon image">
    		</noscript>
  • L’attribut media détermine quelle source est la plus appropriée pour l’affichage de l’utilisateur.
  • Une fois que la bonne source est sélectionnée, l’attribut srcset permet de choisir la bonne densité de pixel, grâce au « 1X, 2x »

Exemple fonctionnel, sans le swich de densité pixel

http://wil.to/picturefill/

Origine de la solution

Cette solution est un hybride entre une solution basée sur la balise picture, et celle basée sur srcset. Florian Rivoal en est à l’origine, via ce post

Le groupe de discussion de la w3c est à l’origine de la démarche de recherche d’une solution propre. Mathew Marquis a fait une synthèse de toutes ces solutions proposés et des recherches du groupe.

Avantages

  • Fonctionne avec les navigateurs sans javascript
  • Pas de perte de bande passante ou de requête http inutile
  • Extensible
  • Compatible avec le futur web qui sera basé sur une des spécifications HTML5

L’élement picture

L’élement picture est une proposition pour la prochaine version des spécification html5, en provenance de la WHATWG. L’idée est justement de pouvoir servir la bonne image en fonction de l’affichage.

L’élément picture est basé sur l’élément html5 < video > et est capable de:

  • contenir plusieurs éléments < source > qui pointent tous vers différentes version du même média image
  • Comprendre nativement les media-queries
  • (optionnel) De spécifier une résolution appropriée pour chaque élément < source >, en utilisant l’attribut srcset à la place de src
  • Proposer une solution de repli pour les navigateurs non compatibles

Tout sur l’élément < picture >

 

Mes sources

– Le fabuleux podcast de Jen Simmons, The Web Ahead, et plus précisément l’épisode #25: Responsive Images with Mat Marquis
– Le livre en Français d’Ethan Marcotte, Responsive design
– Les échanges du groupe de discussion de la w3c

Pour aller plus loin et tester la solution:

https://github.com/scottjehl/picturefill

Intégrateur TYPO3 depuis 2003, maintenant responsable du pôle TYPO3 chez EXL Group. Je réalise des audits, des préconisations, des missions d'expertise. J'ai la chance de diriger le plateau technique Web PHP / TYPO3 d'EXL Group.

3 comments

  1. LuciferX   •  

    Génial, je qui cherchais justement une solution la plus propre possible basée sur le HTML5, merci pour cet excellent article ;-)

  2. Pingback: Le meilleur du web #51: liens, ressources, tutoriels et inspiration « Design Spartan : Art digital, digital painting, webdesign, illustration et inspiration…

  3. MoiMarc   •  

    Bonjour,

    Merci pour votre article, et la solution proposée qui semble élégante au regard de ce que j’ai pû trouver ailleurs sur le web. Une question cependant, sans doute liée à une lacune HTML de ma part : vous dites que si l’élément picture n’est pas supporté, la balise img est affichée, via img alt= »texte alternatif de mon image » src= »extralarge.jpg »

    Pouvez-vous, en quelques lignes, expliquer comment cela fonctionne ? A priori, j’aurais pensé qu’un navigateur ne connaissant pas la balise picture aurait ignoré tout son contenu, en totalité, y compris la balise img incluse ? Même question pour le noscript, en fait…

    Est-ce à dire qu’un navigateur ne connaissant pas une balise, cherchera néanmoins à interpréter son contenu, pour retenir les balises « internes » qu’il reconnait ? Si oui, c’est « fiable » ? Si non, si donc mes suppositions sont fausses, bah j’en reviens à ma demande d’explications ;-)

    D’avance merci

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>