¿Utilizo <img>, <object> o <embed> para archivos SVG?

603

¿Debo usar <img>, <object>o <embed>para cargar archivos SVG en una página de forma similar a cargar un jpg, gifo png?

¿Cuál es el código de cada uno para garantizar que funcione lo mejor posible? (Veo referencias para incluir el tipo MIME o señalar a los renderizadores SVG alternativos en mi investigación y no veo una buena referencia de estado del arte).

Suponga que estoy comprobando la compatibilidad con SVG con Modernizr y retrocediendo (probablemente haciendo un reemplazo con una <img>etiqueta simple ) para navegadores no compatibles con SVG.

artlung
fuente
3
solo eche un vistazo a github.com/jonathantneal/svg4everybody
Machado el
2
Teóricamente, también podría tener uno <svg>desde el que desea hacer referencia a otros SVG. Esto se puede lograr, por ejemplo, usando <image>.
phk

Respuestas:

636

Puedo recomendar el SVG Primer (publicado por el W3C), que cubre este tema: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

Si lo usa <object>, obtendrá una copia de seguridad de la trama gratis *:

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

*) Bueno, no del todo de forma gratuita, ya que algunos navegadores descargan ambos recursos, consulte la sugerencia de Larry a continuación para saber cómo solucionarlo.

Actualización 2014:

  • Si desea un svg no interactivo, úselo <img>con fallos de script a la versión png (para IE y Android anteriores <3). Una manera limpia y simple de hacer eso:

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

    Esto se comportará como una imagen GIF, y si su navegador admite animaciones declarativas (SMIL), se reproducirán.

  • Si desea un svg interactivo, use <iframe>o <object>.

  • Si necesita proporcionar a los navegadores antiguos la capacidad de usar un complemento svg, entonces úselo <embed>.

  • Para svg en css background-imagey propiedades similares, modernizr es una opción para cambiar a imágenes de reserva, otra depende de múltiples fondos para hacerlo automáticamente:

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

    Nota : la estrategia de múltiples fondos no funciona en Android 2.3 porque admite múltiples fondos pero no svg.

Una buena lectura adicional es esta publicación de blog sobre fallos de svg.

Erik Dahlström
fuente
77
¿Cuál es la forma correcta de establecer un tamaño? ¿Incluyo atributos de alto y ancho, o uso CSS?
artlung
55
Usar css está bien, o establecer el tamaño en el elemento de incrustación (es decir, ya sea iframe, embed, object, img); lo que hace este último es evitar el destello de contenido sin estilo antes de la hoja de estilo que define el tamaño está cargado. También asegúrese de que el svg tenga un atributo viewBox y elimine los atributos ancho / alto del elemento raíz svg. Eso te dará el mejor comportamiento de crossbrowser en mi experiencia.
Erik Dahlström
8
Este método siempre descargará el archivo ráster. Esta respuesta asegura que el respaldo solo se solicite en los navegadores IE heredados.
Larry
3
Tenga en cuenta que lo anterior no funciona con el complemento Adobe SVG. Pero puede hacer que todo funcione (navegadores modernos + ASV + MSIE) si agrega <param name="src" value="your.svg" />dentro de la <object>etiqueta. He pasado mucho tiempo tratando de descubrir cómo hacer todo eso, y creo que finalmente lo entendí.
Christopher Schultz
55
Creo que cuanto más rápido la gente deje de admitir navegadores antiguos, más rápido tendremos una sociedad que mantenga sus navegadores actualizados, lo que incluso funciona automáticamente con un navegador a partir de 2012. La única excusa sería no tener acceso gratuito a un navegador moderno, pero Firefox por ejemplo, aún es compatible con Windows XP (probablemente para la versión 52). SIEMPRE hay una alternativa moderna y gratuita.
Neonit
117

Desde IE9 y superior puede usar SVG en una etiqueta IMG ordinaria.

https://caniuse.com/svg-img

<img src="/static/image.svg">
Christian Landgren
fuente
35
Esto no funciona si el SVG requiere que se carguen otros recursos. (Fuentes, imágenes, ...)
TheHippo
11
Para un logotipo o icono, todavía recomendaría usar una etiqueta IMG por razones semánticas y asegurarme de que el SVG sea solo una ilustración vectorial.
Christian Landgren
44
Ahora aceptado en todas partes. @artlung, es posible que desee cambiar su respuesta a esta.
SteeveDroz
16
Cualquiera que use la <img/>etiqueta puede querer saber acerca de agregar identificadores de Fragmentación SVG , por ejemplo " <img src="myimage.svg#svgView(preserveAspectRatio(none))" />", que le permite controlar la relación de aspecto viewBox, etc., lo mismo que con las definiciones SVG en línea. Más información sobre el escalado - css-tricks.com/scale-svg
brichins
101

<object> y <embed> tienen una propiedad interesante: permiten obtener una referencia al documento SVG del documento externo (teniendo en cuenta la política del mismo origen). La referencia se puede utilizar para animar el SVG, cambiar sus hojas de estilo, etc.

Dado

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

Entonces puedes hacer cosas como

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
fuente
No creo que obtendrá un evento de "carga" de un elemento <object>. No soportado.
Steve O'Connor
55
@ SteveO'Connor No lo sé, tal vez no esté bien documentado, pero ciertamente funciona en Firefox, IE11 y Chrome. Al menos con archivos SVG externos: no pude hacer que funcione con URI de datos.
WGH
¡Funciona genial! Curiosamente, parece necesario agregar el campo 'id' cuando tienes dos archivos SVG, de lo contrario, solo aparecerá 1 en mi navegador de Opera.
Bram
¡Obtiene lo mejor de ambos en línea y referenciado con este método!
Brandito
Es bueno saber que los hipervínculos dentro de un SVG no funcionarán a menos que el SVG esté en línea.
Mentalista
26

La mejor opción es usar imágenes SVG en diferentes dispositivos :)

<img src="your-svg-image.svg" alt="Your Logo Alt" onerror="this.src='your-alternative-image.png'">
Roberth Solís
fuente
3
interesante. pero ¿estás seguro de los onerrorincendios si svg no se procesa? ¿Qué navegadores has probado?
artlung
1
Sí, lo pruebo en un sistema operativo Android móvil, navegador predeterminado :)
Roberth Solís
24

Utilizar srcset

La mayoría de los navegadores actuales admiten el srcsetatributo , que permite especificar diferentes imágenes para diferentes usuarios. Por ejemplo, puede usarlo para una densidad de píxeles de 1x y 2x, y el navegador seleccionará el archivo correcto.

En este caso, si especifica un SVG en el srcsety el navegador no lo admite, recurrirá al src.

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

Este método tiene varios beneficios sobre otras soluciones:

  1. No depende de hacks o scripts extraños
  2. Es simple
  3. Todavía puedes incluir texto alternativo
  4. Los navegadores compatibles srcsetdeben saber cómo manejarlo para que solo descargue el archivo que necesita.
Garabato
fuente
55
¿Por qué molestarse dado que hay un> 99% de posibilidades de que cualquier navegador admita SVG en estos días?
Robert Longson
55
Además de garantizar que TODOS puedan ver la página con precisión, ¡Google te amará más!
Pitidos
2
Se ve mejor de lo que es, dado que en el momento actual estás empujando la imagen alternativa a ~ 10% de los usuarios.
Volker E.
2
@VolkerE. 10%? caniuse muestra falta de soporte SVG alrededor del 2% . Todavía uso srcset como en la respuesta para soportar el 2%. En el futuro, espero que los navegadores puedan tomar información como srcset y elegir la imagen adecuada en función de factores como el rendimiento y el tamaño, no solo el tamaño del dispositivo o el formato de archivo.
Scribblemacher
3
El único problema con esta solución es cuando los navegadores admiten SVG pero no srcset. Como IE11, que por defecto vuelve a PNG aunque admite SVG
Hego555
16

Si necesita que sus SVG tengan un estilo completo con CSS, deben estar en línea en el DOM. Esto se puede lograr a través de la inyección SVG, que utiliza Javascript para reemplazar un elemento HTML (generalmente un <img>elemento) con el contenido de un archivo SVG después de que la página se haya cargado.

Aquí hay un ejemplo mínimo con SVGInject :

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

Después de cargar la imagen onload="SVGInject(this), activará la inyección y el <img>elemento será reemplazado por el contenido del archivo provisto en el srcatributo. Esto funciona con todos los navegadores que admiten SVG.

Descargo de responsabilidad: soy coautor de SVGInject

Waruyama
fuente
15

Yo personalmente usaría una <svg>etiqueta porque si lo tienes, tienes control total sobre ella . Si lo usas en<img> no podrá controlar las entrañas del SVG con CSS, etc.

Otra cosa es el soporte del navegador .

Simplemente abra su svgarchivo y péguelo directamente en la plantilla.

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

entonces en tu CSS puedes simplemente, por ejemplo:

svg {
  fill: red;
}

Algún recurso: consejos SVG

LazerBanana
fuente
15

Si usa etiquetas <img> , los navegadores basados ​​en webkit no mostrarán imágenes de mapa de bits incrustadas .

Para cualquier tipo de uso avanzado de SVG, incluidas las ofertas en línea de SVG, con mucho, la mayor flexibilidad.

Internet Explorer y Edge redimensionarán el SVG correctamente , pero debe especificar tanto el alto como el ancho.

Puede agregar onclick, onmouseover, etc. dentro del svg, a cualquier forma en el SVG: onmouseover = "top.myfunction (evt);"

También puedes usar fuentes web en el SVG incluyéndolas en su hoja de estilo regular.

Nota: si está exportando SVG desde Illustrator, los nombres de las fuentes web serán incorrectos. Puede corregir esto en su CSS y evitar perder el tiempo en el SVG. Por ejemplo, Illustrator le da un nombre incorrecto a Arial, y puede arreglarlo así:

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

Todo esto funciona en cualquier navegador lanzado desde 2013 .

Para ver un ejemplo, visite ozake.com . Todo el sitio está hecho de SVG excepto el formulario de contacto.

Advertencia: las fuentes web se redimensionan de manera imprecisa en Safari, y si tiene muchas transiciones de texto sin formato a negrita o cursiva, puede haber una pequeña cantidad de espacio adicional o faltante en los puntos de transición. Vea mi respuesta a esta pregunta para más información.

Andrew Swift
fuente
Gracias. Acabo de pasar 3 horas tirando de mi cabello tratando de descubrir por qué las imágenes de trama no aparecían en mi imgetiqueta ... ¿Sabes si esto está documentado oficialmente en alguna parte?
pan de centeno
@Andrew Swift, obtienes resultados visuales realmente agradables en dev.ozake.com , pero hay serios problemas de accesibilidad: los motores de búsqueda probablemente tendrán dificultades para indexar el sitio (no estoy seguro de que recojan enlaces ocultos en los eventos SVG) ; el sitio no es navegable por teclado; parece que los lectores de pantalla se
ahogarán
11

Mis dos centavos: a partir de 2019, el 93% de los navegadores en uso (y el 100% de las últimas dos versiones de cada uno de ellos) pueden manejar SVG en <img>elementos:

ingrese la descripción de la imagen aquí

Fuente: ¿Puedo usar

Entonces podríamos decir que ya no hay razón para usar <object>.

Sin embargo, todavía tiene sus ventajas :

  • Al inspeccionar (por ejemplo, con Chrome Dev Tools), se le presenta el marcado SVG completo en caso de que quiera manipularlo un poco y ver los cambios en vivo.

  • Proporciona una implementación de respaldo muy robusta en caso de que su navegador no sea compatible con SVG (¡espere, pero todos lo hacen!), Que también funciona si no se encuentra el SVG. Esta fue una característica clave de la especificación XHTML2, que es como betamax o HD-DVD

Pero también hay contras :

ffflabs
fuente
3

Encontré una solución con CSS puro y sin descarga de doble imagen. No es hermoso como quiero, pero funciona.

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

La idea es insertar SVG especial con estilo alternativo.

Puede encontrar más detalles y procesos de prueba en mi blog .

Artru
fuente
0

Esta función jQuery captura todos los errores en las imágenes svg y reemplaza la extensión del archivo con una extensión alternativa

Abra la consola para ver el error al cargar la imagen 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
fuente
-1

Recomiendo usar la combinación de

<svg viewBox="" width="" height="">
<path fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
</svg>
Grv97
fuente
¿Podría explicar por qué usaría esta configuración y por qué es diferente de cualquier otra respuesta?
kvantour
-1

Puede insertar un SVG indirectamente usando <img> etiqueta HTML y esto es posible en StackOverflow siguiendo lo que se describe a continuación:

Tengo el siguiente archivo SVG en mi 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>

He subido esta imagen a https://svgur.com

Después de finalizar la carga, obtuve la siguiente URL:

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

Luego agregué MANUALMENTE (sin usar el icono de IMAGEN) siguiendo la etiqueta html

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

y el resultado está justo debajo

Para el usuario con alguna duda, es posible ver lo que he hecho en la edición después de la respuesta en la inserción de la imagen SVG de StackOverflow

OBSERVACIÓN-1: el archivo SVG debe contener un <?xml?>elemento. Al principio, simplemente he creado un archivo SVG que comienza directamente con la <svg>etiqueta y nada funcionó.

OBSERVACIÓN-2: al principio, intenté insertar una imagen usando el IMAGEícono de Edit Toolbar. Pego la URL de mi archivo SVG pero StackOverflow no acepta este método. los<img> etiqueta debe agregarse manualmente.

Espero que esta respuesta pueda ayudar a otros usuarios.

Schlebe
fuente