Eu uso <img>, <object> ou <embed> para arquivos SVG?


603

Devo usar <img>, <object>ou <embed>para carregar arquivos SVG em uma página de uma forma semelhante ao carregamento de um jpg, gifou png?

Qual é o código de cada um para garantir que funcione da melhor maneira possível? (Estou vendo referências à inclusão do tipo de mimet ou apontando para renderizadores SVG substitutos em minha pesquisa e não vendo uma boa referência do estado da arte).

Suponha que eu esteja verificando o suporte ao SVG com o Modernizr e retornando (provavelmente fazendo uma substituição por uma <img>marca simples ) para navegadores que não sejam compatíveis com SVG.



2
Teoricamente, você também pode ter um a <svg>partir do qual deseja fazer referência a outros SVGs. Isso pode ser alcançado, por exemplo, usando <image>.
Php 29/09/17

Respostas:


636

Posso recomendar o SVG Primer (publicado pelo W3C), que aborda este tópico: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

Se você usar <object>, obterá o fallback de varredura gratuitamente *:

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

*) Bem, não é de graça, porque alguns navegadores baixam os dois recursos, veja a sugestão de Larry abaixo para saber como contornar isso.

Atualização de 2014:

  • Se você deseja um svg não interativo, use <img>com fallbacks de script para a versão png (para IE e android mais antigos <3). Uma maneira limpa e simples de fazer isso:

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

    Isso se comportará como uma imagem GIF e, se o seu navegador suportar animações declarativas (SMIL), elas serão reproduzidas.

  • Se você deseja um svg interativo, use <iframe>ou <object>.

  • Se você precisar fornecer a navegadores antigos a capacidade de usar um plug-in svg, use <embed>.

  • Para svg em css background-imagee propriedades semelhantes, modernizr é uma opção para alternar para imagens de fallback, outra depende de vários fundos para fazê-lo automaticamente:

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

    Nota : a estratégia de vários fundos não funciona no Android 2.3 porque suporta vários fundos, mas não svg.

Uma boa leitura adicional é este post no blog sobre svg fallbacks.


7
Qual é a maneira correta de definir um tamanho? Incluo atributos de altura e largura ou uso CSS?
Artlung

5
Usar css é bom ou definir o tamanho no elemento de incorporação (ou seja, iframe, incorporação, objeto, img) - o que o último faz é evitar o conteúdo sem flash antes da folha de estilo que define o tamanho está carregado. Verifique também se o svg possui um atributo viewBox e remova os atributos width / height do elemento raiz svg. Isso dará a você o melhor comportamento de cross-browser na minha experiência.
Erik Dahlström

8
Esse método sempre baixa o arquivo raster. Esta resposta garante que o fallback seja solicitado apenas em navegadores IE herdados.
Larry

3
Observe que o descrito acima não funciona com o plug-in Adobe SVG. Mas você pode fazer com que tudo funcione (navegadores modernos + ASV + MSIE) se você adicionar <param name="src" value="your.svg" />dentro da <object>tag. Passei muito tempo tentando descobrir como fazer tudo isso, e acho que finalmente consegui.
Christopher Schultz

5
Eu acho que quanto mais rápido as pessoas deixarem de oferecer suporte a navegadores antigos, mais rápido teremos uma sociedade que mantém seus navegadores atualizados, o que até acontece automaticamente com um navegador a partir de 2012. A única desculpa seria não ter acesso gratuito a um navegador moderno, mas o Firefox por exemplo, suporta o Windows XP ainda (provavelmente para a versão 52). Sempre existe uma alternativa moderna e gratuita.
Neonit

117

No IE9 e acima, você pode usar o SVG em uma tag IMG comum.

https://caniuse.com/svg-img

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

35
Isso não funciona se o SVG exigir que outros recursos sejam carregados. (Fontes, imagens, ...)
TheHippo

11
Para um logotipo ou ícone, eu ainda recomendaria o uso de uma tag IMG por razões semânticas e verifique se o SVG é apenas uma ilustração vetorial.
Christian Landgren

4
Agora aceito em todos os lugares. @artlung, você pode querer alterar sua resposta para esta.
SteeveDroz

16
Qualquer pessoa que use a <img/>tag pode querer saber sobre como anexar identificadores SVG Fragement , por exemplo, " <img src="myimage.svg#svgView(preserveAspectRatio(none))" />", que permite controlar a proporção viewBox, etc, da mesma forma que nas definições de SVG embutidas. Leitura adicional sobre dimensionamento - css-tricks.com/scale-svg
brichins

101

<object>e <embed>possuem uma propriedade interessante: permitem obter uma referência ao documento SVG a partir de um documento externo (levando em consideração a política de mesma origem). A referência pode ser usada para animar o SVG, alterar suas folhas de estilo etc.

Dado

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

Você pode fazer coisas 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");
});

Eu não acho que você receberá um evento "load" de um elemento <object>. Não suportado.
Steve O'Connor

5
@ SteveO'Connor Não sei, talvez não esteja bem documentado, mas certamente funciona no Firefox, IE11 e Chrome. Pelo menos com arquivos SVG externos: não consegui fazê-lo funcionar com URIs de dados.
WGH

Funciona bem! Curiosamente, a adição do campo 'id' parece ser necessária quando você tem dois arquivos SVG; caso contrário, apenas 1 aparecerá no meu navegador Opera.
Bram

Você obtém o melhor dos inline e faz referência a este método!
Brandito 29/03

É bom estar ciente de que os hiperlinks dentro de um SVG não funcionarão, a menos que o SVG esteja embutido.
Mentalista

26

A melhor opção é usar imagens SVG em diferentes dispositivos :)

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

3
interessante. mas você tem certeza de que os onerrorincêndios se o svg não renderizar? Quais navegadores você testou?
Artlung

1
Sim, eu testá-lo em um celular Android OS, navegador padrão :)
Roberth Solís

24

Usar srcset

Hoje, asrcset maioria dos navegadores atuais suporta o atributo , que permite especificar imagens diferentes para diferentes usuários. Por exemplo, você pode usá-lo para densidade de pixels de 1x e 2x, e o navegador selecionará o arquivo correto.

Nesse caso, se você especificar um SVG no srcsete o navegador não o suportar, ele fará o fallback no src.

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

Este método possui vários benefícios sobre outras soluções:

  1. Não depende de hacks ou scripts estranhos
  2. É simples
  3. Você ainda pode incluir texto alternativo
  4. Os navegadores que suportam srcsetdevem saber como lidar com isso, para que ele faça o download apenas do arquivo necessário.

5
Por que se preocupar, considerando que há uma chance> 99% de que qualquer navegador suporte SVG atualmente?
Robert Longson 24/03

5
Além de garantir que TODOS possam ver a página com precisão, o Google amará você mais!
Hoots

2
Parece melhor do que é, já que no momento atual você está enviando uma imagem de fallback para ~ 10% dos usuários.
Volker E.

2
@VolkerE. 10%? caniuse mostra falta de suporte SVG em torno de 2% . Eu ainda uso o srcset como na resposta para apoiar os 2%. No futuro, espero que os navegadores possam obter informações como srcset e escolher a imagem apropriada com base em fatores como desempenho e tamanho, não apenas no tamanho do dispositivo ou no suporte ao formato do arquivo.
Scribblemacher

3
O único problema desta solução é quando os navegadores suportam SVG, mas não o srcset. Tais como IE11, cujo padrão voltar para PNG, embora ele suporta SVG
Hego555

16

Se você precisar que seus SVGs sejam totalmente estilizados com CSS, eles deverão estar embutidos no DOM. Isso pode ser alcançado através da injeção SVG, que usa Javascript para substituir um elemento HTML (geralmente um <img>elemento) pelo conteúdo de um arquivo SVG após o carregamento da página.

Aqui está um exemplo mínimo usando SVGInject :

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

Após o carregamento da imagem onload="SVGInject(this), a injeção será acionada e o <img>elemento será substituído pelo conteúdo do arquivo fornecido no srcatributo Isso funciona com todos os navegadores que suportam SVG.

Disclaimer: Eu sou o co-autor do SVGInject


15

Eu pessoalmente usaria uma <svg>tag, porque se você tiver controle total sobre ela . Se você o usar, <img>não poderá controlar as entranhas do SVG com CSS etc.

Outra coisa é o suporte ao navegador .

Basta abrir seu svgarquivo e colá-lo diretamente no modelo.

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

então no seu css você pode simplesmente por exemplo:

svg {
  fill: red;
}

Algum recurso: dicas SVG


15

Se você usar tags <img> , os navegadores baseados no kit da web não exibirão imagens de bitmap incorporadas .

Para qualquer tipo de uso avançado de SVG, incluindo o SVG embutido, oferece de longe a maior flexibilidade.

O Internet Explorer e o Edge redimensionarão o SVG corretamente , mas você deve especificar a altura e a largura.

Você pode adicionar onclick, onmouseover, etc. dentro do svg, a qualquer forma no SVG: onmouseover = "top.myfunction (evt);"

Você também pode usar fontes da Web no SVG incluindo-as em sua folha de estilos comum.

Nota: se você estiver exportando SVGs do Illustrator, os nomes das fontes da Web estarão incorretos. Você pode corrigir isso no seu CSS e evitar mexer no SVG. Por exemplo, o Illustrator atribui o nome errado a Arial e você pode corrigi-lo assim:

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

Tudo isso funciona em qualquer navegador lançado desde 2013 .

Para um exemplo, consulte ozake.com . Todo o site é composto por SVGs, exceto pelo formulário de contato.

Aviso: as fontes da Web são redimensionadas de maneira imprecisa no Safari - e se você tiver muitas transições de texto sem formatação para negrito ou itálico, pode haver uma pequena quantidade de espaço extra ou ausente nos pontos de transição. Veja minha resposta nesta pergunta para obter mais informações.


Obrigado. Passei três horas puxando meu cabelo tentando descobrir por que as imagens raster não estavam aparecendo na minha imgetiqueta ... Você sabe se isso está oficialmente documentado em algum lugar?
ryebread

@ Andrew Swift, você obtém resultados visuais muito bons no dev.ozake.com , mas há sérios problemas de acessibilidade: os mecanismos de pesquisa provavelmente terão dificuldade em indexar o site (não tenho certeza de que eles irão buscar links ocultos nos eventos SVG) ; o site não pode ser navegado pelo teclado; Parece que os leitores de tela irá sufocá-lo ...
interDist

11

Meus dois centavos: a partir de 2019, 93% dos navegadores em uso (e 100% das duas últimas versões de cada um deles) podem manipular SVG em <img>elementos:

insira a descrição da imagem aqui

Fonte: Posso usar

Então, nós poderia dizer que não há nenhuma razão para usar <object>mais.

No entanto , ainda tem seus profissionais :

  • Ao inspecionar (por exemplo, com as Ferramentas de Desenvolvimento do Chrome), você recebe toda a marcação SVG, caso queira mexer um pouco com ela e ver alterações ao vivo.

  • Ele fornece uma implementação de fallback muito robusta, caso seu navegador não suporte SVGs (aguarde, mas todos eles suportam!), O que também funciona se o SVG não for encontrado. Esse era um recurso essencial das especificações XHTML2, que é como betamax ou HD-DVD

Mas também existem contras :


3

Foi encontrada uma solução com CSS puro e sem download de imagem dupla. Não é bonito como eu quero, mas 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>

A idéia é inserir SVG especial com estilo de fallback.

Mais detalhes e processo de teste você pode encontrar no meu blog .


0

Essa função jQuery captura todos os erros nas imagens svg e substitui a extensão do arquivo por uma extensão alternativa

Por favor, abra o console para ver o erro ao carregar a imagem 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

Eu recomendo usar a combinação de

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

você poderia explicar por que você usaria essas configurações e por que é diferente de outras respostas?
precisa saber é o seguinte

-1

Você pode inserir um SVG indiretamente usando a <img>tag HTML e isso é possível no StackOverflow, seguindo o descrito abaixo:

Tenho o seguinte arquivo SVG no meu 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>

Fiz upload desta imagem para https://svgur.com

Após o término do upload, eu obtive o seguinte URL:

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

Em seguida, adicionei MANUALMENTE (sem usar o ícone IMAGE) após a tag html

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

e o resultado está logo abaixo

Para usuários com alguma dúvida, é possível ver o que fiz na edição da seguinte resposta no StackOverflow inserindo imagem SVG

OBSERVAÇÃO-1: o arquivo SVG deve conter o <?xml?>elemento No começo, eu simplesmente criei um arquivo SVG que começa diretamente com a <svg>tag e nada funcionou!

OBSERVAÇÃO-2: no início, tentei inserir uma imagem usando o IMAGEícone de Edit Toolbar. Eu colo o URL do meu arquivo SVG, mas o StackOverflow não aceita esse método. A <img>tag deve ser adicionada manualmente.

Espero que esta resposta possa ajudar outros usuários.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.