Remplacement “responsive” d’image en CSS

Comme nous le savons, la création graphique d’un site passe toujours souvent par la réalisation d’éléments inutilement visuellement complexes.
Avec un peu de chance, voici sur quoi vous pourriez ou avez pu tomber en ouvrant un fichier :


Cette construction artistique se situant certainement dans un mouvement abstrait, futuriste ou art nouveau ne donne malheureusement pas la même satisfaction à toutes les étapes de la conception. Quoique.

Pour être franc, mon point de vue sur ce genre de choses (que je considère dénuées de tout bon sens) est bien arrêté : « Elles ne devront jamais être représentées par une structure HTML complexe et des centaines de lignes CSS imbuvables » .

Pour les autres, je vous laisse en tête à tête avec la citation de Kevin Rocher :

Laisse les donc prouver qu’ils peuvent se faire un croque-monsieur au micro-ondes.

Sur le papier

La demande paraît justifiée et réalisable. Cependant, une fois le story réalisé (pour l’occasion et par moi même), celui-ci a identifié quelques contraintes :

  • L’image d’arrière-plan doit pouvoir être dessinée dans une surface contenant le contenu de taille variable
  • L’image de remplacement ne doit pas être étirée ou déformée (le ratio original doit toujours être préservé)
  • Le ratio intrinsèque doit être calculé en fonction de la largeur de la surface contenant le contenu et non celle de son parent
  • Même si il nous serait facile d’utiliser une balise <img /> (cf : « Un reset “responsive” pour les images. »), il n’y a aucun intérêt à ce que cette information soit présente sous forme d’image si le style n’est pas appliqué (dans le code source de la page).

L’une des techniques les plus connues pour remplacement du texte par une image en CSS est certainement celle du text-indent: -9999px; pour laquelle il a été proposé une récente alternative tout à fait honorable mais qui a toutefois ses limites.
Pour ceux qui aime les choses plus « .ir » , vous avez la solution proposée par Nicolas Gallagher (“Another CSS image replacement technique”) qui a elle aussi été remplacée sans trop de bruit par celle-ci dans le projet HTML5 Boilerplate.

Le fait est qu’aucune de ces solutions ne répond à mon besoin. Elles nécessitent toutes de définir une hauteur (et une largeur dans beaucoup de cas) à notre contenant pour afficher l’image de remplacement.
En m’arrêtant là, je serai inévitablement entraîné (pour ne pas dire obligé d’aller) vers la mise en place de solutions spécifiques qui peuvent être démultipliées en fonction des cas.

Dans la pratique

.rwd-ir {
  max-width: 308px; /* Natural width */
  background-image: url(le-client-et-le-graphiste-ont-toujours-raison.png);
  background-size: 100%;

  font: 0/0 a;
}
.rwd-ir:before {
  display: block;
  padding: 32.4675% 0 0; /* Height in percent (Natural height: 100px) */
  content: "";
}

Ça se passe plutôt bien. Ça ne paraît pas !

Que font chaques déclarations ?

  • max-width: 308px; – Permet de s’assurer que la largeur naturelle de l’image ne sera jamais dépassée.
  • background-size: 100%; – Spécifie que l’image d’arrière-plan doit être mise à l’échelle pour être aussi grande que possible sur la largeur de la zone de contenu.
    Dans le cas où une/des marges intérieures seraient appliquées, les déclarations background-origin: content-box; et background-repeat: no-repeat; devront être ajoutées pour que le fond soit peint uniquement dans la zone de contenu et éviter la répétition.
  • .rwd-ir:before {} – Donne à la surface contenant le contenu un format spécifique qui respecte le ratio de l’image de remplacement et cela par rapport à sa propre largeur.
    Cette méthode est inspirée de celle utilisée dans SUIT flexible embed ou FitVids.js pour ne citer qu’eux. À la seule différence que je profite d’un pseudo-élément.

Ce qu’il faut savoir

Aucun hack de remplacement n’est parfait.
Celui au dessus a lui aussi ses limites (même s’il a plutôt bien marché lors de mon dernier projet) :

  • L’utilisation de la propriété background-size impose ses limites dans IE 8. Dans les cas simples, un polyfill suffira. Dans les plus complexes, dans les plus complexes…
  • Cette approche exclut complètement le support d’IE 7. Je n’ai pas de regrets à cela car elle n’a pas été pensée pour.
  • Comme beaucoup de méthodes de remplacement, elles ne fonctionnent pas si les CSS sont chargées mais que les images ne le sont pas. Que voulez-vous, nous ne pouvons pas tout avoir.

Pour finir

Les possibilités pour résoudre ce problème sont à coup sûr infinies mais en restant raisonnable (et en sachant ce que vous faites) cette technique s’utilisera sans encombre.

Laisser un commentaire

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