Uso <img>, <object> o <embed> per i file SVG?


603

Dovrei usare <img>, <object>o <embed>per caricare file SVG in una pagina in modo simile al caricamento di un jpg, gifo png?

Qual è il codice per ognuno per garantire che funzioni nel miglior modo possibile? (Sto vedendo riferimenti per includere il mimetipo o indicare i renderer SVG di fallback nella mia ricerca e non vedo un riferimento allo stato dell'arte).

Supponiamo che stia verificando il supporto SVG con Modernizr e ricadendo (probabilmente facendo una sostituzione con un <img>tag semplice ) per i browser non compatibili con SVG.



2
Teoricamente, potresti anche avere una <svg>da cui vuoi fare riferimento ad altri SVG. Ciò può essere ottenuto, ad esempio utilizzando <image>.
phk,

Risposte:


636

Posso consigliare SVG Primer (pubblicato dal W3C), che tratta questo argomento: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

Se lo usi <object>, ricevi un raster fallback gratuito *:

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

*) Beh, non del tutto gratis, perché alcuni browser scaricano entrambe le risorse, vedi il suggerimento di Larry qui sotto per come aggirare questo.

Aggiornamento 2014:

  • Se si desidera uno svg non interattivo, utilizzare <img>con gli script fallback alla versione png (per IE precedenti e Android <3). Un modo semplice e pulito per farlo:

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

    Questo si comporterà in modo molto simile a un'immagine GIF e se il tuo browser supporta animazioni dichiarative (SMIL), queste verranno riprodotte.

  • Se vuoi uno svg interattivo, usa <iframe>o <object>.

  • Se è necessario fornire ai browser meno recenti la possibilità di utilizzare un plug-in svg, utilizzare <embed>.

  • Per svg in CSS background-imagee proprietà simili, modernizr è una scelta per passare a immagini di fallback, un'altra dipende da più sfondi per farlo automaticamente:

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

    Nota : la strategia a più sfondi non funziona su Android 2.3 perché supporta più sfondi ma non svg.

Un'ulteriore buona lettura è questo post sul blog sui fallback svg.


7
Qual è il modo giusto per impostare una taglia? Includo attributi di altezza e larghezza o utilizzo i CSS?
artlung,

5
Usare css va bene, o impostare la dimensione sull'elemento embedding (ovvero: iframe, embed, object, img) - ciò che fa quest'ultimo è evitare il flash-of-unstyled-content prima del foglio di stile che definisce la dimensione è caricato. Assicurati anche che svg abbia un attributo viewBox e rimuovi gli attributi larghezza / altezza dall'elemento radice svg. Questo ti darà il miglior comportamento dei crossbrowser nella mia esperienza.
Erik Dahlström,

8
Questo metodo scaricherà sempre il file raster. Questa risposta garantisce che il fallback sia richiesto solo sui browser IE legacy.
Larry,

3
Si noti che quanto sopra non funziona con il plug-in Adobe SVG. Ma puoi far funzionare tutto (browser moderni + ASV + MSIE) se aggiungi<param name="src" value="your.svg" /> all'interno del <object>tag. Ho passato molto tempo a cercare di capire come fare tutto questo, e penso di averlo finalmente capito.
Christopher Schultz,

5
Penso che più velocemente le persone smetteranno di supportare i browser antichi più velocemente avremo una società che mantiene aggiornati i loro browser, che va anche automaticamente con un browser dal 2012. L'unica scusa sarebbe di non avere accesso gratuito a un browser moderno, ma Firefox ad esempio supporta ancora Windows XP (probabilmente alla versione 52). C'è SEMPRE un'alternativa moderna e gratuita.
Neonit

117

Da IE9 in poi è possibile utilizzare SVG in un normale tag IMG.

https://caniuse.com/svg-img

<img src="/static/image.svg">

35
Questo non funziona se l'SVG richiede il caricamento di altre risorse. (Font, immagini, ...)
TheHippo,

11
Per un logo o un'icona consiglierei comunque di utilizzare un tag IMG per motivi semantici e assicurarmi che SVG sia solo un'illustrazione vettoriale.
Christian Landgren,

4
Ora accettato ovunque. @artlung, potresti voler cambiare la tua risposta a questa.
SteeveDroz,

16
Chiunque utilizzi il <img/>tag potrebbe voler conoscere l'aggiunta di identificativi di frazionamento SVG , ad esempio " <img src="myimage.svg#svgView(preserveAspectRatio(none))" />", che consente di controllare le proporzioni viewBox, ecc. Lo stesso delle definizioni SVG in linea. Ulteriori letture sul ridimensionamento - css-tricks.com/scale-svg
brichins

101

<object>e <embed>hanno una proprietà interessante: consentono di ottenere un riferimento al documento SVG dal documento esterno (tenendo conto della politica della stessa origine). Il riferimento può quindi essere utilizzato per animare l'SVG, modificarne i fogli di stile, ecc.

Dato

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

È quindi possibile fare cose come

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");
});

Non credo che otterrai un evento "load" da un elemento <object>. Non supportato.
Steve O'Connor,

5
@ SteveO'Connor Non lo so, forse non è ben documentato, ma sicuramente funziona su Firefox, IE11 e Chrome. Almeno con file SVG esterni: non sono riuscito a farlo funzionare con gli URI dei dati.
WGH,

Funziona alla grande! È interessante notare che l'aggiunta del campo "id" sembra essere richiesta quando si hanno due file SVG, altrimenti solo 1 verrà visualizzato nel mio browser Opera?
Bram,

Ottieni il meglio da entrambi in linea e referenziato con questo metodo!
Brandito

È bene essere consapevoli del fatto che i collegamenti ipertestuali all'interno di un SVG non funzioneranno se lo SVG non è in linea.
Mentalista,

26

L'opzione migliore è utilizzare le immagini SVG su diversi dispositivi :)

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

3
interessante. ma sei sicuro che gli onerrorincendi se svg non viene visualizzato? quali browser hai testato?
artlung

1
Sì, l'ho testato su un sistema operativo Android mobile, browser predefinito :)
Roberth Solís,

24

Uso srcset

La maggior parte dei browser attuali supporta l' srcsetattributo , che consente di specificare immagini diverse per utenti diversi. Ad esempio, puoi usarlo per densità di pixel 1x e 2x e il browser selezionerà il file corretto.

In questo caso, se si specifica un file SVG in srcsete il browser non lo supporta, verrà eseguito il fallback su src.

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

Questo metodo ha diversi vantaggi rispetto ad altre soluzioni:

  1. Non si basa su alcuno strano hack o script
  2. È semplice
  3. Puoi ancora includere il testo alternativo
  4. I browser che supportano srcsetdovrebbero sapere come gestirlo in modo che scarichi solo il file di cui ha bisogno.

5
Perché preoccuparsi dato che esiste una probabilità> 99% che un browser supporti SVG in questi giorni?
Robert Longson,

5
A parte il fatto che TUTTI possono vedere la pagina in modo accurato, Google ti adorerà di più!
Hoots,

2
Sembra migliore di quello che è, dato che al momento attuale stai spingendo l'immagine di fallback a circa il 10% degli utenti.
Volker E.

2
@VolkerE. 10%? caniuse mostra una mancanza di supporto SVG intorno al 2% . Uso ancora srcset come nella risposta per supportare il 2%. In futuro, spero che i browser siano in grado di acquisire informazioni come srcset e scegliere l'immagine appropriata in base a fattori come prestazioni e dimensioni, non solo le dimensioni del dispositivo o il supporto del formato file.
Scribblemacher,

3
L'unico problema con questa soluzione è quando i browser supportano SVG ma non srcset. Come IE11, il cui valore predefinito è PNG anche se supporta SVG
Hego555

16

Se hai bisogno che i tuoi SVG siano completamente personalizzabili con i CSS, devono essere in linea nel DOM. Ciò può essere ottenuto tramite l'iniezione SVG, che utilizza Javascript per sostituire un elemento HTML (di solito un<img> elemento) con il contenuto di un file SVG dopo il caricamento della pagina.

Ecco un esempio minimo usando SVGInject :

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

Dopo che l'immagine è stata caricata, onload="SVGInject(this)si innescherà l'iniezione e l' <img>elemento sarà sostituito dal contenuto del file fornito insrc nell'attributo. Funziona con tutti i browser che supportano SVG.

Disclaimer: sono il coautore di SVGInject


15

Personalmente userei un <svg>tag perché se lo fai hai il pieno controllo su di esso . Se lo usi in <img>non puoi controllare le viscere dell'SVG con CSS ecc.

un'altra cosa è il supporto del browser .

Basta aprire il svgfile e incollarlo direttamente nel modello.

<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>

quindi nel tuo CSS puoi semplicemente ad esempio:

svg {
  fill: red;
}

Alcune risorse: suggerimenti SVG


15

Se si utilizzano tag <img> , i browser basati su webkit non visualizzeranno immagini bitmap incorporate .

Per qualsiasi tipo di utilizzo avanzato di SVG, comprese le offerte in linea SVG di gran lunga la massima flessibilità.

Internet Explorer e Edge ridimensioneranno correttamente SVG , ma è necessario specificare sia l'altezza che la larghezza.

Puoi aggiungere onclick, onmouseover, ecc. All'interno di svg, a qualsiasi forma in SVG: onmouseover = "top.myfunction (evt);"

È inoltre possibile utilizzare i caratteri Web in SVG includendoli nel normale foglio di stile.

Nota: se si stanno esportando SVG da Illustrator, i nomi dei caratteri Web saranno errati. Puoi correggerlo nel tuo CSS ed evitare di perdere tempo in SVG. Ad esempio, Illustrator dà il nome sbagliato ad Arial e puoi risolverlo in questo modo:

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

Tutto questo funziona su qualsiasi browser rilasciato dal 2013 .

Per un esempio, vedi ozake.com . L'intero sito è costituito da SVG tranne il modulo di contatto.

Avvertenza: i caratteri Web vengono ridimensionati in modo impreciso in Safari - e se si hanno molte transizioni da testo normale a grassetto o corsivo, potrebbe esserci una piccola quantità di spazio extra o mancante nei punti di transizione. Vedi la mia risposta a questa domanda per ulteriori informazioni.


Grazie. Ho appena trascorso 3 ore a strapparmi i capelli cercando di capire perché le immagini raster non erano presenti nel mio imgtag ... Sai se questo è ufficialmente documentato da qualche parte?
Ryebread

@Andrew Swift, ottieni risultati visivi davvero belli su dev.ozake.com , ma ci sono seri problemi di accessibilità: i motori di ricerca probabilmente avranno difficoltà a indicizzare il sito (non sono sicuro che raccoglieranno collegamenti nascosti all'interno degli eventi SVG) ; il sito non è navigabile da tastiera; sembra che gli screen reader si
strozzeranno

11

I miei due centesimi: a partire dal 2019, il 93% dei browser in uso (e il 100% delle ultime due versioni di ognuno di essi) può gestire SVG in <img>elementi:

inserisci qui la descrizione dell'immagine

Fonte: posso usare

Così abbiamo potuto dire che non c'è alcun motivo per utilizzare <object>più.

Tuttavia ha ancora i suoi pro :

  • Durante l'ispezione (ad es. Con Chrome Dev Tools) ti viene presentato l'intero markup SVG nel caso in cui volessi manometterlo un po 'e vedere le modifiche in tempo reale.

  • Fornisce un'implementazione di fallback molto solida nel caso in cui il tuo browser non supporti gli SVG (aspetta, ma ognuno di loro lo fa!) Che funziona anche se l'SVG non viene trovato. Questa era una caratteristica chiave delle specifiche XHTML2, che è come betamax o HD-DVD

Ma ci sono anche contro :


3

Trovato una soluzione con CSS puro e senza download di immagini doppie. Non è bello come voglio, ma funziona.

<!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'idea è quella di inserire un SVG speciale con stile di fallback.

Maggiori dettagli e processo di test che puoi trovare nel mio blog .


0

Questa funzione jQuery cattura tutti gli errori nelle immagini svg e sostituisce l'estensione del file con un'estensione alternativa

Apri la console per visualizzare l' errore durante il caricamento dell'immagine 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">


-1

Consiglio di usare la combinazione di

<svg viewBox="" width="" height="">
<path fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
</svg>

potresti approfondire il motivo per cui dovresti utilizzare queste impostazioni e perché è diverso da qualsiasi altra risposta?
kvantour,

-1

È possibile inserire un SVG indirettamente utilizzando <img> tag HTML e questo è possibile su StackOverflow seguendo quanto descritto di seguito:

Ho seguito il file SVG sul mio 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>

Ho caricato questa immagine su https://svgur.com

Dopo che il caricamento è stato terminato, ho ottenuto il seguente URL:

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

Ho quindi aggiunto MANUALMENTE (senza usare l'icona IMMAGINE) seguendo il tag html

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

e il risultato è appena sotto

Per l'utente con qualche dubbio, è possibile vedere cosa ho fatto nella modifica dopo la risposta su StackOverflow inserendo l'immagine SVG

NOTA: 1: il file SVG deve contenere <?xml?>elementi. All'inizio, ho semplicemente creato un file SVG che inizia direttamente con il <svg>tag e nulla ha funzionato!

NOTA: 2, all'inizio, ho provato a inserire un'immagine usando l' IMAGEicona di Edit Toolbar. Ho incollato l'URL del mio file SVG ma StackOverflow non accetta questo metodo. Il<img> tag deve essere aggiunto manualmente.

Spero che questa risposta possa aiutare gli altri utenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.