web-dev-qa-db-fra.com

Est-ce que j'utilise <img>, <objet> ou <embed> pour les fichiers SVG?

Dois-je utiliser <img>, <object> ou <embed> pour charger des fichiers SVG dans une page de la même manière que pour charger une jpg, gif ou png?

Quel est le code pour chacun pour s'assurer qu'il fonctionne le mieux possible? (Je vois des références à l'inclusion du type MIME ou des pointages sur des rendus SVG de repli dans mes recherches et à l'absence d'une bonne référence de l'état de l'art).

Supposons que je vérifie le support SVG avec Modernizr et que je me replie (probablement en effectuant un remplacement avec une balise plain <img>) pour les navigateurs non compatibles SVG.

549
artlung

Je peux recommander SVG Primer (publié par le W3C), qui couvre ce sujet: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

Si vous utilisez <object>, vous bénéficiez d'un repli de trame gratuit *:

<object data="your.svg" type="image/svg+xml">
  <img src="yourfallback.jpg" />
</object>

*) Eh bien, pas tout à fait gratuitement, car certains navigateurs téléchargent les deux ressources, voir la suggestion de Larry ci-dessous pour savoir comment résoudre ce problème.

Mise à jour 2014:

  • Si vous voulez un svg non interactif, utilisez <img> avec les substitutions de script à la version png (pour les anciens IE et Android <3). Une façon simple et propre de le faire:

    <img src="your.svg" onerror="this.src='your.png'">.

    Cela se comportera presque comme une image GIF. Si votre navigateur prend en charge les animations déclaratives (SMIL), celles-ci sont lues.

  • Si vous voulez un svg interactif, utilisez soit <iframe> ou <object>.

  • Si vous devez fournir aux anciens navigateurs la possibilité d'utiliser un plug-in svg, utilisez <embed>.

  • Pour svg dans les fichiers css background-image et les propriétés similaires, modernizr est un choix pour basculer vers des images de secours. Un autre choix dépend de plusieurs arrière-plans pour le faire automatiquement:

    div {
        background-image: url(fallback.png);
        background-image: url(your.svg), none;
    }
    

    Note : la stratégie d'arrière-plans multiples ne fonctionne pas sur Android 2.3 car il prend en charge plusieurs arrière-plans mais pas svg.

Une bonne lecture supplémentaire est this blogpost sur les repli de svg.

589
Erik Dahlström

À partir de IE9 et plus, vous pouvez utiliser SVG dans un tag IMG ordinaire.

https://caniuse.com/svg-img

<img src="/static/image.svg">
100
Christian Landgren

<object> et <embed> ont une propriété intéressante: ils permettent d'obtenir une référence à un document SVG à partir d'un document externe (en tenant compte de la politique de même origine). La référence peut ensuite être utilisée pour animer le SVG, modifier ses feuilles de style, etc.

Donné

<object id="svg1" data="/static/image.svg" type="image/svg+xml"></object>

Vous pouvez ensuite faire des choses comme

document.getElementById("svg1").addEventListener("load", function() {
    var doc = this.getSVGDocument();
    var rect = doc.querySelector("rect"); // suppose our image contains a <rect>
    rect.setAttribute("fill", "green");
});
93
WGH

La meilleure option consiste à utiliser des images SVG sur différents appareils :)

<img src="your-svg-image.svg" alt="Your Logo Alt" onerror="this.src='your-alternative-image.png'">
22
Roberth Solís

Utilisez srcset

La plupart les navigateurs actuels prennent en charge l'attribut srcset , ce qui permet de spécifier différentes images pour différents utilisateurs. Par exemple, vous pouvez l’utiliser pour des densités de 1x et 2x pixels et le navigateur sélectionnera le fichier correct.

Dans ce cas, si vous spécifiez un fichier SVG dans la variable srcset et que le navigateur ne la prend pas en charge, le repli est effectué sur la src.

<img src="logo.png" srcset="logo.svg" alt="My logo">

Cette méthode présente plusieurs avantages par rapport à d’autres solutions:

  1. Il ne s'appuie pas sur des hacks ou des scripts étranges
  2. C'est simple
  3. Vous pouvez toujours inclure du texte alternatif
  4. Les navigateurs qui prennent en charge srcset doivent savoir comment le gérer afin de ne télécharger que le fichier dont il a besoin.
20
Scribblemacher

Si vous utilisez <img> balises, alors les navigateurs Webkit gagnés ' t affiche les images bitmap incorporées .

Si vous utilisez des SVG en ligne, alors Explorer ne redimensionnera pas le SVG en fonction de vos CSS.
Explorer redimensionnera correctement le fichier SVG , mais vous devez spécifier la hauteur et la largeur.

J'ai constaté que la balise <object> est la seule qui fonctionne sur tous les navigateurs. J'ai dû changer la largeur et la hauteur (à l'intérieur du SVG) à 100% afin de le redimensionner correctement.

Vous pouvez ajouter onclick, onmouseover, etc. à l'intérieur du svg, à n'importe quelle forme du fichier SVG: onmouseover = "top.myfunction (evt);"

Vous pouvez également utiliser des polices Web dans le fichier SVG en les incluant dans votre feuille de style habituelle.

Remarque: si vous exportez des SVG à partir d'Illustrator, les noms de police Web seront incorrects. Vous pouvez corriger cela dans votre CSS et éviter de vous perdre dans le SVG. . Par exemple, Illustrator donne le mauvais nom à Arial et vous pouvez le corriger comme ceci:

@font-face {    
    font-family: 'ArialMT';    
    src:    
        local('Arial'),    
        local('Arial MT'),    
        local('Arial Regular');    
    font-weight: normal;    
    font-style: normal;    
}

Tout cela fonctionne sur tous les navigateurs sortis au cours des deux dernières années .

Résultats sur ozake.com (en français). L'ensemble du site est constitué de SVG, à l'exception du formulaire de contact.

Avertissement: les polices Web ne sont pas redimensionnées avec précision. Si vous avez beaucoup de transitions du texte brut en gras ou en italique, il peut rester une petite quantité d'espace supplémentaire ou manquant au niveau de la transition. points. Voir ma réponse à cette question pour plus d'informations.

15
Andrew Swift

Si vous voulez que vos SVG soient entièrement stylables avec CSS, ils doivent être intégrés au DOM. Cela peut être réalisé par injection SVG, qui utilise Javascript pour remplacer un élément HTML (généralement un élément <img>) par le contenu d'un fichier SVG après le chargement de la page.

Voici un exemple minimal utilisant SVGInject :

<html>
<head>
  <script src="svg-inject.min.js"></script>
</head>
<body>
  <img src="image.svg" onload="SVGInject(this)" />
</body>
</html>

Une fois l'image chargée, la onload="SVGInject(this) déclenchera l'injection et l'élément <img> sera remplacé par le contenu du fichier fourni dans l'attribut src. Cela fonctionne avec tous les navigateurs supportant SVG.

Disclaimer: Je suis co-auteur de SVGInject

14
Waruyama

Personnellement, j'utiliserais une balise <svg> parce que si vous en avez le contrôle . Si vous l'utilisez dans <img>, vous ne pouvez pas contrôler les entrailles du SVG avec CSS, etc.

une autre chose est support du navigateur .

Ouvrez simplement votre fichier svg et collez-le directement dans le modèle.

<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3400 2700" preserveAspectRatio="xMidYMid meet" (click)="goHome();">
  <g id="layer101">
    <path d="M1410 2283 c-162 -225 -328 -455 -370 -513 -422 -579 -473 -654 -486 -715 -7 -33 -50 -247 -94 -475 -44 -228 -88 -448 -96 -488 -9 -40 -14 -75 -11 -78 2 -3 87 85 188 196 165 180 189 202 231 215 25 7 129 34 230 60 100 26 184 48 185 49 4 4 43 197 43 212 0 10 -7 13 -22 9 -13 -3 -106 -25 -208 -49 -102 -25 -201 -47 -221 -51 l-37 -7 8 42 c4 23 12 45 16 49 5 4 114 32 243 62 129 30 240 59 246 66 10 10 30 132 22 139 -1 2 -110 -24 -241 -57 -131 -33 -240 -58 -242 -56 -6 6 13 98 22 107 5 4 135 40 289 80 239 61 284 75 307 98 14 15 83 90 153 167 70 77 132 140 139 140 7 0 70 -63 141 -140 70 -77 137 -150 150 -163 17 -19 81 -39 310 -97 159 -41 292 -78 296 -82 8 -9 29 -106 24 -111 -1 -2 -112 24 -245 58 -134 33 -245 58 -248 56 -6 -7 16 -128 25 -136 5 -4 112 -30 238 -59 127 -29 237 -54 246 -57 11 -3 20 -23 27 -57 6 -28 9 -53 8 -54 -1 -1 -38 7 -81 17 -274 66 -379 90 -395 90 -16 0 -16 -6 3 -102 11 -57 21 -104 22 -106 1 -1 96 -27 211 -57 115 -31 220 -60 234 -66 14 -6 104 -101 200 -211 95 -111 175 -197 177 -192 1 5 -40 249 -91 542 l-94 532 -145 203 c-220 309 -446 627 -732 1030 -143 201 -265 366 -271 367 -6 0 -143 -183 -304 -407z m10 -819 l-91 -161 -209 -52 c-115 -29 -214 -51 -219 -49 -6 1 32 55 84 118 l95 115 213 101 c116 55 213 98 215 94 1 -3 -38 -78 -88 -166z m691 77 l214 -99 102 -123 c56 -68 100 -125 99 -127 -4 -3 -435 106 -447 114 -4 2 -37 59 -74 126 -38 68 -79 142 -93 166 -13 23 -22 42 -20 42 2 0 101 -44 219 -99z"/>
    <path d="M1126 2474 c-198 -79 -361 -146 -363 -147 -2 -3 -70 -410 -133 -805 -12 -73 -20 -137 -18 -143 2 -6 26 23 54 63 27 40 224 320 437 622 213 302 386 550 385 551 -2 2 -165 -62 -362 -141z"/>
    <path d="M1982 2549 c25 -35 159 -230 298 -434 139 -203 283 -413 319 -465 37 -52 93 -134 125 -182 59 -87 83 -109 73 -65 -5 20 -50 263 -138 747 -17 91 -36 170 -42 176 -9 8 -571 246 -661 280 -14 6 -7 -10 26 -57z"/>
    <path d="M1679 1291 c-8 -11 -71 -80 -141 -153 l-127 -134 -95 -439 c-52 -242 -92 -442 -90 -445 6 -5 38 28 218 223 l99 107 154 0 c85 0 163 -4 173 -10 10 -5 78 -79 151 -162 73 -84 136 -157 140 -162 18 -21 18 4 -2 85 -11 46 -58 248 -105 448 l-84 364 -87 96 c-108 121 -183 201 -187 201 -2 0 -10 -9 -17 -19z m96 -488 c33 -102 59 -189 57 -192 -2 -6 -244 -2 -251 4 -5 6 120 375 127 375 4 0 34 -84 67 -187z"/>
    </g>
  </svg>

alors dans votre css vous pouvez simplement par exemple:

svg {
  fill: red;
}

Quelques ressources: SVG tips

10
LazerBanana

Mes deux cents: à partir de 2019, 93% des navigateurs utilisés (et 100% des deux dernières versions de chacune d'entre elles) peuvent gérer le SVG avec des éléments <img>:

enter image description here

Source: Puis-je utiliser

Donc, nous pourrions dire qu'il n'y a plus de raison d'utiliser <object>.

Cependant ​​il a toujours ses avantages:

  • Lors de l'inspection (par exemple avec ChromeDev Tools), le balisage SVG complet vous est présenté au cas où vous souhaiteriez le modifier un peu et voir les modifications en direct.

  • Il fournit une implémentation de secours très robuste au cas où votre navigateur ne supporte pas les SVG (attendez, mais chacun d'entre eux le fait!), Ce qui fonctionne également si le SVG n'est pas trouvé. C’était une caractéristique clé de la spécification XHTML2, qui ressemble à betamax ou HD-DVD

Mais il y a aussi cons:

7
amenadiel

Trouvé une solution avec du CSS pur et sans téléchargement de double image. Ce n'est pas beau comme je veux, mais ça marche.

<!DOCTYPE html>
<html>
  <head>
    <title>HTML5 SVG demo</title>
    <style type="text/css">
     .nicolas_cage {
         background: url('nicolas_cage.jpg');
         width: 20px;
         height: 15px;
     }
     .fallback {
     }
    </style>
  </head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
    <style>
    <![CDATA[ 
        .fallback { background: none; background-image: none; display: none; }
    ]]>
    </style>
</svg>

<!-- inline svg -->
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40">
  <switch>
     <circle cx="20" cy="20" r="18" stroke="grey" stroke-width="2" fill="#99FF66" />
     <foreignObject>
         <div class="nicolas_cage fallback"></div>
     </foreignObject>
  </switch>
</svg>
<hr/>
<!-- external svg -->
    <object type="image/svg+xml" data="circle_orange.svg">
        <div class="nicolas_cage fallback"></div>
    </object>
</body>
</html>

L'idée est d'insérer du SVG spécial avec un style de repli.

Plus de détails et le processus de test que vous pouvez trouver dans mon blog .

2
Artru

Cette fonction jQuery capture toutes les erreurs dans les images svg et remplace l'extension de fichier par une autre extension

Veuillez ouvrir la console pour voir le erreur lors du chargement de l'image svg

(function($){
  $('img').on('error', function(){
    var image = $(this).attr('src');
    if ( /(\.svg)$/i.test( image )) {
      $(this).attr('src', image.replace('.svg', '.png'));
    }
  })  
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<img src="https://jsfiddle.net/img/logo.svg">
0
Andres Separ