Niveau Niveau confirmé

Un logo cliquable SVG avec alternatives

Tutorielhtml

Publié par le , mis à jour le (82190 lectures)

css webdesign svg

“Responsive Webdesign”, “Retina”, “optimisation mobile”, autant de termes qui sont devenus de plus en plus présents dans nos quotidiens de designers et intégrateurs web. Le nombre d’écrans dont la résolution permet l’affiche d’images en très haute qualité ne cesse d’augmenter : écrans Retina sur iPhone, téléphones Android, Mac Book pro et bientôt sur nos TV (à quand le frigo ?), etc.
Ces nouveaux écrans apportent de nouvelles perspectives, mais également un besoin grandissant de flexibilité. Le format vectoriel semble être une excellente réponse à cette problématique.

Cet article s'intéressera au format SVG qui propose une solution flexible : une seule image vectorielle, qui pourra être redimensionnée et s’afficher dans différentes tailles sur tout support sans perte de qualité.

Nous verrons ici un exemple très concret : l’utilisation sur un site du SVG pour le logo cliquable qui renvoie à l’accueil de notre site. Nous ne voulons pas pénaliser les utilisateurs dont les navigateurs ne supportent pas le SVG, donc nous allons leur proposer un fallback (alternative) en PNG.

Plusieurs méthodes sont proposées dans cet article, avec ou sans l’utilisation de JavaScript, avec à chaque fois avantages et inconvénients. À vous de faire le choix de celle qui conviendra le mieux à votre projet.

Voir la démonstration 

Voir le code sur github 

(Note : le code est libre de droit vous pouvez le ré-utiliser comme bon vous semble, à l’exception du logo Geeks and the City prêté pour la démo)

Le SVG, c’est quoi ?

Avant de chercher comment inclure notre logo SVG dans une page, un petit rappel sur ce qu’est exactement ce format. SVG est l'acronyme de Scalable Vector Graphic, un langage XML utilisé pour décrire des graphiques en 2 dimensions. Puisque les images sont générées “en code” à base de formes géométriques et non de pixels, elles sont “zoomables” à l’infini et on peut les redimensionner sans perte de qualité (à condition bien sûr de respecter les proportions sous peine d’avoir une distorsion de l’image).

Un petit exemple de code, pour dessiner un carré noir :

<?xml version="1.0" encoding="utf-8"?>
<svg width="150" height="100" xmlns="http://www.w3.org/2000/svg"> 
   <desc> Mon carré noir </desc> 
   <rect width="150" height="100" fill="#000" /> 
</svg>

Pour les plus motivés qui souhaitent plus d’informations sur la syntaxe du SVG je vous conseille le tutoriel SVG, le dessin vectoriel pour le web.

Pas de panique pour nos amis designers, vous pourrez utiliser vos logiciels de dessin vectoriel préférés pour des images plus complexes. Les logiciels Illustrator et Inkscape gèrent très bien la création de fichier .svg et il existe même une extension pour Fireworks dédiée.

Quelques règles de base cependant à respecter pour que vos images SVG soient compatibles avec le maximum de navigateurs possibles : 

  • Evitez les dégradés trop compliqués, préférez les dégradés linéaires et radiaux; l'outil d’Illustator pour créer le dégradé de filet est à proscrire.
  • N’utilisez pas les effets Photoshop proposés dans Illustrator qui se basent sur un rendu pixel.
  • Pensez à nommer vos groupes et calques (vous le faites déjà de toute façon, non ?).
  • Utilisez le pathfinder autant que possible pour fusionner les formes et générer des formes pleines.
  • Dans le doute, transformez vos textes en formes vectorielles. 

Screenshot du logo SVG sous Illustrator avec les calques nommés

En résumé : gardez vos SVGs générés depuis un logiciel de dessin les plus simples possible, et testez leur rendu dans différents navigateurs (glisser-déposer de l’image directement dans le navigateur).

Pour notre exemple, nous utilisons un logo sans dégradés, le texte a été transformé en objets vectoriels, et les différentes zones qui ont la même couleur ont été rassemblées.

Nous pouvons désormais passer au vif du sujet, l’intégration de notre logo dans une page avec un fallback pour les navigateurs qui ne supportent pas le SVG (voir le tableau de support)

L’utilisation de la balise <object> et le fallback <img>

Une des premières solutions proposées pour intégrer l’image SVG avant l 'arrivée du HTML5 est la balise object, oui celle-là même qu’on utilisait pour Flash, vous vous souvenez ? Ici le fallback sera une simple image dans une balise <img>.

 
 

Le code HTML

<a href="#" >
   <object class="logo" data="logo.svg" width="186" height="235" type="image/svg+xml"> 
      <img class="logo" src="logo.png" width="186" height="235" alt="Logo Geeks and the City" />
   </object>
</a>

Le gros problème avec l’utilisation de la balise object est le lien. Si on ne passe pas le lien en display:block, il n’est pas cliquable. Et même avec le lien en display:block, le logo lui-même n’est pas cliquable mais uniquement le lien derrière. La solution n’est donc pas idéale dans l’état pour un logo de retour à l’accueil.

Avantages :

  • le fallback est simple
  • le fallback fonctionne sans JavaScript d’activé

Inconvénients :

  • le lien n’est pas cliquable dans la zone du logo, ni affiché correctement
  • les navigateurs qui supportent le SVG vont télécharger les deux images

L’utilisation de la balise <svg> avec un fallback <foreignObject>

Le HTML5 a introduit la balise <svg>, prévue justement pour intégrer de la syntaxe SVG directement dans la page web. Il est donc possible, avec le bon doctype, de copier directement le contenu du fichier SVG dans le HTML. Pour cela il vous suffit d’ouvrir le fichier dans votre éditeur de code préféré et de recopier ce qui se situe entre le début et la fin de la balise <svg>.

Le fallback utilisera la balise <foreignObject> qui permet d’inclure des éléments externes dans le SVG. Nous y placerons notre image de fallback en PNG.

 
 

Le code : 

<a href="#" >
<svg  class="logo" width="186px" height="235px">
   <!-- Tout mon code SVG -->
   <switch>
      <foreignObject width="0" height="0" overflow="hidden">
         <img class="logo" src="logo.png" width="186" height="235" alt="Logo Geeks and the City" />
      </foreignObject>
   </switch>
</svg>
</a>

Avantages

  • le lien fonctionne
  • le fallback fonctionne même en désactivant le JavaScript

Inconvénients

  • il faut copier/coller le contenu du fichier SVG, cette technique manque donc cruellement de flexibilité dans le cas d’un CMS par exemple
  • tous les navigateurs n’implémentent pas encore cette technique de la même façon

Les solutions basées sur la balise <img>

Il est également possible de traiter une image SVG comme n’importe quelle autre image, et donc d’utiliser pour cela la balise <img>

L’utilisation de la balise <img> et une capture d’erreur en JavaScript en fallback

Cette technique a été proposée sur le blog de Tavmjong Bah qui suggère de détecter le support du SVG en capturant une erreur JavaScript, puis de remplacer le SVG par un PNG si le navigateur ne supporte pas le SVG et renvoie l’erreur.

 
 
 
Le code
<a href="#catching_error" >
   <img class="logo" src="logo.svg" width="186" height="235" alt="Logo Geeks and the City" onerror="this.removeAttribute('onerror'); this.src='logo.png'" />
</a>
Avantages
  • le lien fonctionne
  • le code est très simple et le seul ajout est le petit morceau de JavaScript
Inconvénients
  • le fallback requiert l’activation de JavaScript

L’utilisation de la balise <img>, avec un arrière plan CSS en fallback

Cette technique se base sur modernizr pour détecter le support du SVG. S’il est supporté, une class .svg sera ajoutée à la balise html, sinon une classe .no-svg. Il est donc possible d’utiliser ces classes pour proposer une image de fallback en arrière plan pour notre SVG.

 
Le HTML utilisé
<a href="#modernizr_css_fallback" >
   <img class="logo" src="logo.svg" width="186" height="235" alt="Logo Geeks and the City" />
</a>
Le CSS de cette technique
#modernizr_css_fallback img.logo {
   display: none;
}
#modernizr_css_fallback a {
   display: block;
   width: 186px;
   height: 235px;
   background-image: url(logo.png);
   background-color: transparent;
   text-indent: -9999px;
   color: transparent;
   margin: 0 auto;
}
.svg #modernizr_css_fallback img.logo {  
   display:block;
}
.svg #modernizr_css_fallback a {
   background: none; 
}

Pour cette méthode, nous sommes obligés de tricher, car Internet Explorer va afficher l’attribut alt de notre SVG. Nous allons donc dans un premier temps cacher l’image, puis appliquer l’arrière plan sur le lien, auquel nous allons donner les dimensions souhaitées de l’image. 

Screenshot du logo avec Internet explorer qui affiche l'attribut alt

 

Si le SVG est supporté, nous allons utiliser la class .svg pour afficher l’image, et retirer l’arrière plan du lien pour ne pas faire doublon.

Avantages
  • le lien fonctionne
  • le fallback fonctionne avec JavaScript désactivé
Inconvénients
  • la technique est assez bancale et on triche un peu pour ajouter l’arrière plan à la balise <a> et non à l’image
  • si le JavaScript est désactivé, les navigateurs qui supportent le SVG vont afficher le fallback en PNG

L’utilisation de la balise <a>, avec une detection SVG Modernizr pour proposer un fallback avec data-fallback

Cette technique se base sur l’attribut data-* pour proposer une image de fallback en PNG. Elle utilise la detection du support SVG de modernizr pour remplacer le SVG par son équivalent PNG si ce premier n’est pas supporté.

 
 
Le code HTML
<a href="#img_modernizr_js_remplacement_bis" >
    <img class="logo" src="logo.svg" width="186" height="235" data-fallback="logo.png" alt="Logo Geeks and the City" />
</a>
Le JavaScript de detection et remplacement du SVG
if(!Modernizr.svg) {
   var imgs = $('img[data-fallback]');
   imgs.attr('src', imgs.data('fallback'));
}
Avantages
  • le lien fonctionne
  • le code HTML est simple à comprendre et pas de balise supplémentaire n’est ajoutée
Inconvénients
  • le fallback requiert l’activation du JavaScript pour fonctionner

L’utilisation de la balise <img> avec du JavaScript et <noscript> en fallback

Cette technique est très proche de la précédente, mais cette fois nous n’allons déclarer dans le HTML que la balise <noscript> qui contiendra notre image PNG si le JavaScript est désactivé. Nous allons ensuite encore une fois nous servir de la détection du SVG de Modernizr pour soit charger le SVG, soit l’image PNG.

 
 
Le code HTML
<a href="#img_modernizr_js_remplacement_nojs">
   <noscript><img class="logo" src="logo.png" width="186" height="235" alt="Logo Geeks and the City" /></noscript>
</a>
Le JavaScript pour passer d’un SVG à un PNG et vice versa
if(Modernizr.svg) {
   $('#img_modernizr_js_remplacement_nojs .header a').html('<img class="logo" src="logo.svg" width="186" height="235" alt="Logo Geeks and the City"/>');
}
else {
   $('#img_modernizr_js_remplacement_nojs .header a').html('<img class="logo" src="logo.png" width="186" height="235" alt="Logo Geeks and the City">');
}
Avantages
  • le lien fonctionne
  • le fallback fonctionne même si le JavaScript est désactivé
Inconvénients
  • si le JavaScript est désactivé, les navigateurs qui supportent le SVG vont afficher l’image PNG

Déclarer le format SVG côté serveur.

Pour que votre logo SVG fonctionne correctement, il se peut que vous ayez à le déclarer côté serveur. Voici le code à ajouter au .htaccess

AddType image/svg+xml svg svgz
AddEncoding gzip svgz

Aller plus loin, un peu de lecture

Conclusion

Cet article présente six méthodes pour utiliser un logo SVG cliquable en en-tête de site web, chacune a ses avantages et inconvénients. Il en existe certainement d'autres. À vous de trouver celle qui vous conviendra le mieux en fonction des besoins de votre projet.

Commentaires

Merci beaucoup, inpixelitrust ! (Quoique pour l'occasion tu aurais pu te rebaptiser "inbezieritrust". Huhuhu.) Pour mon site, j'ai utilisé la technique avec la balise <img> et la capture d'erreur en JavaScript.

Très bon tuto, je me demandais justement si la techno était mure pour une utilisation au quotidien. Pour ma part, je pense effectivement privilégier la technique de la balise img + javascript, mais en mutualisant le fallback javascript avec jQuery. Un truc du genre :
<a href="#catching_error" >
<img class="logo svg" src="logo.svg" data-srcfallback="logo.png" width="186" height="235" alt="Logo Geeks and the City" />
</a>

et dans le jquery :

$(document).ready(function(){

$('.svg').error(function() {
$(this).attr("src", $(this).attr('data-srcfallback'));
})
});

J'avais besoin de paramétrer mon svg : montrer / cacher des items... donc il me fallait le déclarer en <object> et le paramétrer. J'ai choisi, pour le rendre cliquable, de lui passer en paramètre le lien à atteindre et de mettre le lien dans le code du svg, lequel est modifiable grâce au paramètre passé. Je peux donc avoir un même dessin, réemployé plusieurs fois dans une page (icone), qui envoie vers des destinations distinctes en cas de click.Attention, il faut bien mettre "target=_top" dans la déclaration du lien. Inconvénient : ne marche que sur les navigateurs qui acceptent le javascript dans les svg, et quand même un peu compliqué...

@Stéphanie : que penses-tu de la bibliothèque Raphaeljs qui convertit le SVG, et qui est rétrocompatible jusqu'à IE6 ? Je l'utilise et je trouve son utilisation intéressante.

Une question de béotien : comment intégrer une police dans le SVG si on utilise la balise img (comme dans la méthode 2) ?

En utilisant la méthode 1 (avec <object>), on peut référencer la police avec un code du genre de celui qui sort de FontSquirrel :
<defs><style type="text/css"><![CDATA[
@font-face {

font-family: 'xxx';

src: url('xxx.eot');

src: url('xxx.eot?#iefix') format('embedded-opentype'),

url('xxx.woff') format('woff'),

url('xxx.ttf') format('truetype'),

url('xx.svg#xxx') format('svg');
} ]]></style></defs>

Ca n'a pas l'air de marcher quand le SVG est référencé par une balise img.
Y a-t-il une astuce pour s'en sortir ?