Dois-je utiliser <img>, <object> ou <embed> pour les fichiers SVG?

603

Dois - je utiliser <img>, <object>ou <embed>pour le chargement des fichiers SVG dans une page d'une manière similaire à un chargement jpg, gifou png?

Quel est le code de chacun pour s'assurer qu'il fonctionne le mieux possible? (Je vois des références à l'inclusion du type MIME ou pointant vers des rendus SVG de secours dans mes recherches et je ne vois pas une bonne référence de pointe).

Supposons que je vérifie la prise en charge de SVG avec Modernizr et que je recule (faisant probablement un remplacement avec une <img>balise simple ) pour les navigateurs non compatibles SVG.

artlung
la source
3
jetez un œil sur github.com/jonathantneal/svg4everybody
Machado
2
Théoriquement, vous pouvez également en avoir un à <svg>partir duquel vous souhaitez référencer d'autres SVG. Ceci peut être réalisé, par exemple en utilisant <image>.
phk

Réponses:

636

Je peux recommander le 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 obtenez gratuitement un raster fallback *:

<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, consultez la suggestion de Larry ci-dessous pour savoir comment contourner cela.

Mise à jour 2014:

  • Si vous voulez un svg non interactif, utilisez-le <img>avec des scripts de secours en version png (pour les anciens IE et android <3). Une façon propre et simple de le faire:

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

    Cela se comportera un peu comme une image GIF, et si votre navigateur prend en charge les animations déclaratives (SMIL), celles-ci seront lues.

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

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

  • Pour svg dans css background-imageet des propriétés similaires, modernizr est un choix pour passer aux images de secours, un autre dépend de plusieurs arrière-plans pour le faire automatiquement:

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

    Remarque : la stratégie à arrière-plans multiples ne fonctionne pas sur Android 2.3 car elle prend en charge plusieurs arrière-plans mais pas svg.

Une bonne lecture supplémentaire est ce blog sur les solutions de secours svg.

Erik Dahlström
la source
7
Quelle est la bonne façon de définir une taille? Dois-je inclure des attributs de hauteur et de largeur, ou dois-je utiliser CSS?
artlung
5
L'utilisation de css est correcte ou la définition de la taille sur l'élément d'intégration (c'est-à-dire: iframe, embed, object, img) - ce que ce dernier fait, c'est qu'il peut éviter le contenu flash non-stylé avant la feuille de style qui définit la taille est chargé. Assurez-vous également que le svg possède un attribut viewBox et supprimez les attributs width / height de l'élément racine svg. Cela vous donnera le meilleur comportement de croiseur de mon expérience.
Erik Dahlström
8
Cette méthode télécharge toujours le fichier raster. Cette réponse garantit que la solution de secours n'est demandée que sur les navigateurs IE hérités.
Larry
3
Notez que ce qui précède ne fonctionne pas avec le plug-in Adobe SVG. Mais, vous pouvez tout faire fonctionner (navigateurs modernes + ASV + MSIE) si vous ajoutez <param name="src" value="your.svg" />à l'intérieur de la <object>balise. J'ai passé beaucoup de temps à essayer de comprendre comment faire tout cela, et je pense que j'ai enfin compris.
Christopher Schultz
5
Je pense que plus les gens cesseront de prendre en charge les anciens navigateurs, plus vite nous aurons une société qui gardera leurs navigateurs à jour, qui va même automatiquement avec un navigateur à partir de 2012. La seule excuse serait de ne pas avoir accès gratuitement à un navigateur moderne, mais Firefox par exemple, prend en charge Windows XP (probablement jusqu'à la version 52). Il existe TOUJOURS une alternative moderne et gratuite.
Neonit
117

Depuis IE9 et au-dessus, vous pouvez utiliser SVG dans une balise IMG ordinaire.

https://caniuse.com/svg-img

<img src="/static/image.svg">
Christian Landgren
la source
35
Cela ne fonctionne pas si le SVG nécessite le chargement d'autres ressources. (Polices, images, ...)
TheHippo
11
Pour un logo ou une icône, je recommanderais toujours d'utiliser une balise IMG pour des raisons sémantiques et de m'assurer que le SVG n'est qu'une illustration vectorielle.
Christian Landgren
4
Maintenant accepté partout. @artlung, vous voudrez peut-être changer votre réponse à celle-ci.
SteeveDroz
16
Toute personne utilisant la <img/>balise peut vouloir savoir comment ajouter des identifiants SVG Fragement , par exemple " <img src="myimage.svg#svgView(preserveAspectRatio(none))" />", qui vous permet de contrôler le rapport hauteur / largeur viewBox, etc. de la même manière qu'avec les définitions SVG en ligne. Pour en savoir plus sur la mise à l'échelle - css-tricks.com/scale-svg
brichins
101

<object>et <embed>ont une propriété intéressante: elles permettent d'obtenir une référence au 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, changer 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");
});
WGH
la source
Je ne pense pas que vous obtiendrez un événement "load" à partir d'un élément <object>. Non supporté.
Steve O'Connor
5
@ SteveO'Connor Je ne sais pas, peut-être que ce n'est pas bien documenté, mais cela fonctionne certainement dans Firefox, IE11 et Chrome. Au moins avec les fichiers SVG externes: je ne pouvais pas le faire fonctionner avec les URI de données.
WGH
Fonctionne très bien! Fait intéressant, l'ajout du champ «id» semble être requis lorsque vous avez deux fichiers SVG, sinon un seul apparaîtra dans mon navigateur d'opéra?
Bram
Vous obtenez le meilleur des deux en ligne et référencé avec cette méthode!
Brandito
Il est bon de savoir que les hyperliens à l'intérieur d'un SVG ne fonctionneront que si le SVG est en ligne.
Mentalist
26

La meilleure option est d'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'">
Roberth Solís
la source
3
intéressant. mais êtes-vous assuré des onerrorincendies si svg ne s'affiche pas? quels navigateurs avez-vous testés?
artlung
1
Oui, je le teste sur un système d'exploitation Android mobile, navigateur par défaut :)
Roberth Solís
24

Utilisation srcset

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

Dans ce cas, si vous spécifiez un SVG dans le srcsetet que le navigateur ne le prend pas en charge, il se repliera sur le 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 repose 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 srcsetdoivent savoir comment le gérer afin qu'il télécharge uniquement le fichier dont il a besoin.
Scribblemacher
la source
5
Pourquoi s'inquiéter étant donné qu'il y a plus de 99% de chances qu'un navigateur supporte SVG ces jours-ci?
Robert Longson
5
En plus de s'assurer que TOUT LE MONDE peut voir la page avec précision, Google vous aimera plus!
Hoots
2
Il semble meilleur qu'il ne l'est, étant donné qu'à l'heure actuelle, vous transmettez l'image de secours à environ 10% des utilisateurs.
Volker E.
2
@VolkerE. dix%? caniuse montre un manque de support SVG d' environ 2% . J'utilise quand même srcset comme dans la réponse pour supporter les 2%. À l'avenir, j'espère que les navigateurs seront capables de prendre des informations comme srcset et de choisir l'image appropriée en fonction de facteurs tels que les performances et la taille, et pas seulement la taille de l'appareil ou la prise en charge du format de fichier.
Scribblemacher
3
Le seul problème avec cette solution est lorsque les navigateurs prennent en charge SVG mais pas srcset. Tels que IE11, qui revient par défaut à PNG même s'il prend en charge SVG
Hego555
16

Si vous avez besoin que vos SVG soient entièrement stylables avec CSS, ils doivent être en ligne dans le DOM. Cela peut être réalisé grâce à l'injection SVG, qui utilise Javascript pour remplacer un élément HTML (généralement un <img>élément) 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 onload="SVGInject(this), l' <img>élément déclenchera l'injection et l' élément sera remplacé par le contenu du fichier fourni dans l' srcattribut. Cela fonctionne avec tous les navigateurs qui prennent en charge SVG.

Avertissement: je suis le co-auteur de SVGInject

Waruyama
la source
15

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

une autre chose est le support du navigateur .

Ouvrez simplement votre svgfichier 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: conseils SVG

LazerBanana
la source
15

Si vous utilisez des balises <img> , les navigateurs Webkit n'afficheront pas les images bitmap incorporées .

Pour tout type d'utilisation avancée du SVG, y compris le SVG en ligne offre de loin la plus grande flexibilité.

Internet Explorer et Edge redimensionneront correctement le SVG , mais vous devez spécifier à la fois la hauteur et la largeur.

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

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

Remarque: si vous exportez des SVG depuis Illustrator, les noms des polices Web seront incorrects. Vous pouvez corriger cela dans votre CSS et éviter de déconner 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 n'importe quel navigateur sorti depuis 2013 .

Pour un exemple, voir ozake.com . L'ensemble du site est réalisé en SVG à l'exception du formulaire de contact.

Avertissement: les polices Web sont redimensionnées de manière imprécise dans Safari - et si vous avez beaucoup de transitions du texte brut en gras ou en italique, il peut y avoir une petite quantité d'espace supplémentaire ou manquant aux points de transition. Voir ma réponse à cette question pour plus d'informations.

Andrew Swift
la source
Je vous remercie. Je viens de passer 3 heures à m'arracher les cheveux pour essayer de comprendre pourquoi les images tramées n'apparaissaient pas dans mon imgtag ... Savez-vous si cela est officiellement documenté quelque part?
ryebread
@Andrew Swift, vous obtenez de très bons résultats visuels sur dev.ozake.com , mais il y a de sérieux problèmes d'accessibilité: les moteurs de recherche auront probablement du mal à indexer le site (je ne suis pas sûr qu'ils ramasseront des liens cachés dans les événements SVG) ; le site n'est pas navigable par clavier; semble que les lecteurs d'écran s'étoufferont dessus ...
interDist
11

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

entrez la description de l'image ici

Source: puis-je utiliser

On pourrait donc dire qu'il n'y a plus de raison de l'utiliser <object>.

Cependant, il a encore ses avantages :

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

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

Mais il y a aussi des inconvénients :

ffflabs
la source
3

Trouvé une solution avec du CSS pur et sans double téléchargement d'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 un SVG spécial avec un style de secours.

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

Artru
la source
0

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 l' erreur de 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">

Andres Separ
la source
-1

Je recommande d'utiliser la combinaison de

<svg viewBox="" width="" height="">
<path fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
</svg>
Grv97
la source
pourriez-vous expliquer pourquoi vous utiliseriez ces paramètres et pourquoi est-il différent des autres réponses?
kvantour
-1

Vous pouvez insérer un SVG indirectement en utilisant <img> balise HTML et cela est possible sur StackOverflow en suivant ce qui est décrit ci-dessous:

J'ai le fichier SVG suivant sur mon PC

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="350" height="350" viewBox="0 0 350 350">

  <title>SVG 3 Circles Intersection </title>

    <circle cx="110" cy="110" r="100"
            stroke="red"
            stroke-width="3"
            fill="none"
            />
    <text x="110" y="110" 
          text-anchor="middle"
          stroke="red"
          stroke-width="1px"
          > Label
    </text>
    <circle cx="240" cy="110" r="100" 
            stroke="blue" 
            stroke-width="3"
            fill="none"
            />
    <text x="240" y="110" 
          text-anchor="middle" 
          stroke="blue" 
          stroke-width="1px"
          > Ticket
    </text>
    <circle cx="170" cy="240" r="100" 
            stroke="green" 
            stroke-width="3" 
            fill="none"
            />
    <text x="170" y="240" 
          text-anchor="middle" 
          stroke="green" 
          stroke-width="1px"
          > Vecto
    </text>
</svg>

J'ai téléchargé cette image sur https://svgur.com

Une fois le téléchargement terminé, j'ai obtenu l'URL suivante:

https://svgshare.com/i/H7d.svg

J'ai ensuite MANUELLEMENT (sans utiliser l'icône IMAGE) ajouté la balise html suivante

<img src="https://svgshare.com/i/Kyp.svg"/>

et le résultat est juste en dessous

Pour les utilisateurs ayant des doutes, il est possible de voir ce que j'ai fait en modifiant la réponse suivante sur StackOverflow en insérant une image SVG

REMARQUE-1: le fichier SVG doit contenir un <?xml?>élément. Au début, j'ai simplement créé un fichier SVG qui commence directement avec le <svg>tag et rien n'a fonctionné!

REMARQUE-2: au début, j'ai essayé d'insérer une image en utilisant l' IMAGEicône de Edit Toolbar. Je colle l'URL de mon fichier SVG mais StackOverflow n'accepte pas cette méthode. le<img> balise doit être ajoutée manuellement.

J'espère que cette réponse pourra aider d'autres utilisateurs.

schlebe
la source