Czy używam <img>, <object> lub <embed> dla plików SVG?

603

Powinno się używać <img>, <object>lub <embed>do wczytywania plików SVG do strony w sposób podobny do załadowania jpg, gifalbo png?

Jaki jest kod dla każdego, aby upewnić się, że działa tak dobrze, jak to możliwe? (Widzę odniesienia do włączenia typu mimetycznego lub wskazujące na renderery SVG zastępcze w moich badaniach i nie widzę dobrego odniesienia do stanu techniki).

Załóżmy, że sprawdzam obsługę SVG w programie Modernizr i wycofuję się (prawdopodobnie robię zamianę zwykłym <img>tagiem) dla przeglądarek nieobsługujących SVG.

artlung
źródło
3
wystarczy spojrzeć na github.com/jonathantneal/svg4everybody
Machado
2
Teoretycznie możesz mieć również plik, <svg>z którego chcesz odwoływać się do innych plików SVG. Można to osiągnąć np <image>. Za pomocą .
phk

Odpowiedzi:

635

Mogę polecić SVG Primer (opublikowany przez W3C), który obejmuje ten temat: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

Jeśli użyjesz <object>, otrzymasz awarię rastrową bezpłatnie *:

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

*) Cóż, nie całkiem za darmo, ponieważ niektóre przeglądarki pobierają oba zasoby, zobacz sugestię Larry'ego, jak się obejść.

Aktualizacja 2014:

  • Jeśli chcesz mieć nieinteraktywny plik SVG, użyj <img>ze skryptami zastępczymi do wersji png (dla starszych IE i Androida <3). Jeden czysty i prosty sposób to zrobić:

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

    Będzie to zachowywać się podobnie jak obraz GIF, a jeśli Twoja przeglądarka obsługuje animacje deklaratywne (SMIL), to one będą odtwarzane.

  • Jeśli chcesz interaktywną SVG, użyj jednej <iframe>lub <object>.

  • Jeśli chcesz zapewnić starszym przeglądarkom możliwość korzystania z wtyczki svg, użyj <embed>.

  • Dla svg w css background-imagei podobnych właściwościach modernizr to jeden wybór do przejścia do obrazów rezerwowych, inny zależy od wielu środowisk, aby to zrobić automatycznie:

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

    Uwaga : strategia wielu środowisk nie działa na Androidzie 2.3, ponieważ obsługuje wiele środowisk, ale nie svg.

Dodatkową dobrą lekturą jest ten post na blogach o awariach SVG.

Erik Dahlström
źródło
7
Jaki jest właściwy sposób ustawienia rozmiaru? Czy dołączam atrybuty wysokości i szerokości, czy też używam CSS?
artlung,
5
Używanie css jest w porządku, lub ustawianie rozmiaru elementu do osadzania (czyli: iframe, embed, object, img) - to ostatnie pozwala uniknąć flashowania niezstylowanej zawartości przed arkuszem stylów, który określa rozmiar jest załadowana. Upewnij się także, że svg ma atrybut viewBox i usuń atrybuty width / height z elementu głównego svg. To da ci najlepsze zachowanie crossbrowser w moim doświadczeniu.
Erik Dahlström,
8
Ta metoda zawsze pobierze plik rastrowy. Ta odpowiedź zapewnia, że ​​wycofanie jest wymagane tylko w starszych przeglądarkach IE.
Larry,
3
Pamiętaj, że powyższe nie działa z wtyczką Adobe SVG. Ale możesz sprawić, by wszystko działało (nowoczesne przeglądarki + ASV + MSIE), jeśli dodasz <param name="src" value="your.svg" />wewnątrz <object>tagu. Spędziłem bardzo dużo czasu próbując wymyślić, jak to wszystko zrobić i myślę, że w końcu to zrozumiałem.
Christopher Schultz,
5
Myślę, że im szybciej ludzie przestaną obsługiwać starożytne przeglądarki, tym szybciej będziemy mieć społeczeństwo, które aktualizuje ich przeglądarki, co nawet idzie automatycznie z przeglądarką od 2012 roku. Jedynym usprawiedliwieniem byłoby brak wolnego dostępu do nowoczesnej przeglądarki, ale Firefox np. nadal obsługuje Windows XP (prawdopodobnie do wersji 52). ZAWSZE jest nowoczesna i darmowa alternatywa.
Neonit
116

Od wersji IE9 i nowszych możesz używać SVG w zwykłym tagu IMG ..

https://caniuse.com/svg-img

<img src="/static/image.svg">
Christian Landgren
źródło
35
To nie działa, jeśli SVG wymaga załadowania innych zasobów. (Czcionki, obrazy, ...)
TheHippo
10
W przypadku logo lub ikony nadal zalecałbym używanie tagu IMG ze względów semantycznych i upewnienie się, że SVG jest tylko ilustracją wektorową.
Christian Landgren,
4
Teraz akceptowane wszędzie. @artlung, możesz zmienić swoją odpowiedź na to.
SteeveDroz
15
Każdy, kto używa tego <img/>znacznika, może chcieć wiedzieć o dołączaniu identyfikatorów Fragement SVG , np. „ <img src="myimage.svg#svgView(preserveAspectRatio(none))" />”, Który pozwala kontrolować proporcje viewBoxitp. Tak samo, jak w przypadku wbudowanych definicji SVG. Dalsza lektura na temat skalowania - css-tricks.com/scale-svg
brichins
101

<object>i <embed>mają ciekawą właściwość: umożliwiają uzyskanie odniesienia do dokumentu SVG z dokumentu zewnętrznego (biorąc pod uwagę zasady tego samego pochodzenia). Odniesienia można następnie użyć do animacji SVG, zmiany arkuszy stylów itp.

Dany

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

Możesz wtedy robić takie rzeczy jak

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
źródło
Nie sądzę, że dostaniesz zdarzenie „load” z elementu <object>. Niewspierany.
Steve O'Connor
5
@ SteveO'Connor Nie wiem, może nie jest to dobrze udokumentowane, ale z pewnością działa w Firefox, IE11 i Chrome. Przynajmniej z zewnętrznymi plikami SVG: Nie mogłem sprawić, by działał z identyfikatorami URI danych.
WGH
Działa świetnie! Co ciekawe, dodanie pola „id” wydaje się być wymagane, gdy masz dwa pliki SVG, w przeciwnym razie tylko 1 pojawi się w mojej przeglądarce operowej?
Bram
Dostajesz to, co najlepsze zarówno w trybie bezpośrednim, jak i referencyjnym dzięki tej metodzie!
Brandito
Dobrze jest mieć świadomość, że hiperłącza wewnątrz pliku SVG nie będą działać, chyba że plik SVG jest wbudowany.
Mentalista
26

Najlepszą opcją jest użycie obrazów SVG na różnych urządzeniach :)

<img src="your-svg-image.svg" alt="Your Logo Alt" onerror="this.src='your-alternative-image.png'">
Roberth Solís
źródło
3
ciekawy. ale czy masz pewność, że onerrorpożary, jeśli svg się nie renderuje? jakie przeglądarki przetestowałeś?
artlung
1
Tak,
testuję
24

Posługiwać się srcset

Większość obecnych przeglądarek obsługuje obecnie ten srcsetatrybut , który umożliwia określanie różnych obrazów dla różnych użytkowników. Na przykład możesz użyć go do gęstości 1x i 2x pikseli, a przeglądarka wybierze odpowiedni plik.

W takim przypadku, jeśli określisz plik SVG w srcsetprzeglądarce, a przeglądarka go nie obsługuje , nastąpi powrót do niego src.

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

Ta metoda ma kilka zalet w porównaniu z innymi rozwiązaniami:

  1. Nie polega na żadnych dziwnych włamaniach ani skryptach
  2. To proste
  3. Nadal możesz dołączyć tekst alternatywny
  4. Przeglądarki, które obsługują, srcsetpowinny wiedzieć, jak sobie z tym poradzić, aby pobierał tylko potrzebny plik.
Pisarz
źródło
5
Po co zawracać sobie głowy tym, że istnieje obecnie> 99% szansa, że ​​każda przeglądarka będzie obsługiwać SVG?
Robert Longson
5
Częścią jest zapewnienie, że KAŻDY może dokładnie zobaczyć stronę, Google pokocha Cię bardziej!
Hoots
2
Wygląda lepiej niż jest, biorąc pod uwagę, że obecnie przesuwasz obraz zastępczy do ~ 10% użytkowników.
Volker E.
2
@VolkerE. 10%? Caniuse pokazuje brak wsparcia SVG około 2% . Nadal jednak używam srcset jak w odpowiedzi do obsługi 2%. Mam nadzieję, że w przyszłości przeglądarki będą mogły pobierać informacje takie jak srcset i wybierać odpowiedni obraz na podstawie czynników takich jak wydajność i rozmiar, a nie tylko rozmiar urządzenia lub obsługa formatu pliku.
Scribblemacher
3
Jedynym problemem z tym rozwiązaniem jest to, że przeglądarki obsługują SVG, ale nie srcset. Takich jak IE11, która domyślnie wraca do PNG, mimo że obsługuje SVG
Hego555
16

Jeśli potrzebujesz, aby pliki SVG były w pełni stylizowane za pomocą CSS, muszą być wbudowane w DOM. Można to osiągnąć poprzez wstrzyknięcie SVG, który używa Javascript do zastąpienia elementu HTML (zwykle <img>elementu) zawartością pliku SVG po załadowaniu strony.

Oto minimalny przykład użycia SVGInject :

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

Po załadowaniu obrazu onload="SVGInject(this)uruchomi się zastrzyk, a <img>element zostanie zastąpiony zawartością pliku podanego w srcatrybucie. Działa to ze wszystkimi przeglądarkami obsługującymi SVG.

Oświadczenie: Jestem współautorem SVGInject

Waruyama
źródło
15

Osobiście użyłbym <svg>tagu, ponieważ jeśli masz pełną kontrolę nad nim . Jeśli go użyjesz, nie <img>będziesz w stanie kontrolować wewnętrznych elementów SVG za pomocą CSS itp.

Inną rzeczą jest obsługa przeglądarki .

Wystarczy otworzyć svgplik i wkleić go bezpośrednio do szablonu.

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

następnie w swoim css możesz po prostu np .:

svg {
  fill: red;
}

Niektóre zasoby: wskazówki SVG

LazerBanana
źródło
15

Jeśli używasz znaczników <img> , przeglądarki oparte na pakiecie webkit nie będą wyświetlać osadzonych obrazów bitmapowych .

Do wszelkiego rodzaju zaawansowanych zastosowań SVG, w tym wbudowanych ofert SVG, zdecydowanie najbardziej elastyczna.

Internet Explorer i Edge poprawnie zmienią rozmiar SVG , ale musisz podać zarówno wysokość, jak i szerokość.

Możesz dodać onclick, onmouseover itp. Wewnątrz svg, do dowolnego kształtu w SVG: onmouseover = "top.myfunction (evt);"

Możesz także używać czcionek internetowych w SVG, umieszczając je w swoim zwykłym arkuszu stylów.

Uwaga: jeśli eksportujesz pliki SVG z programu Illustrator, nazwy czcionek internetowych będą nieprawidłowe. Możesz to naprawić w swoim CSS i uniknąć bałaganu w SVG. Na przykład program Illustrator nadaje niewłaściwą nazwę Arialowi i można to naprawić w następujący sposób:

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

Wszystko to działa na dowolnej przeglądarce wydanej od 2013 roku .

Na przykład zobacz ozake.com . Cała strona jest wykonana z SVG, z wyjątkiem formularza kontaktowego.

Ostrzeżenie: Czcionki internetowe są nieprecyzyjnie zmieniane w Safari - a jeśli masz wiele przejść od zwykłego tekstu do pogrubienia lub kursywy, w punktach przejścia może być niewielka ilość dodatkowego lub brakującego miejsca. Aby uzyskać więcej informacji, zobacz moją odpowiedź na to pytanie .

Andrew Swift
źródło
Dziękuję Ci. Właśnie spędziłem 3 godziny na rozczesywaniu włosów, próbując dowiedzieć się, dlaczego obrazy rastrowe nie pojawiały się w moim imgtagu ... Czy wiesz, czy jest to oficjalnie udokumentowane?
ryebread
@Andrew Swift, masz naprawdę dobre wyniki wizualne na dev.ozake.com , ale istnieją poważne problemy z dostępnością: wyszukiwarki prawdopodobnie będą miały trudności z indeksowaniem strony (nie jestem pewien, czy wybiorą linki ukryte w wydarzeniach SVG) ; strona nie jest nawigowana za pomocą klawiatury; wygląda na to, że czytniki ekranu będą się dusić ...
interDist
11

Moje dwa centy: od 2019 r. 93% używanych przeglądarek (i 100% dwóch ostatnich wersji każdej z nich) może obsługiwać SVG w <img>elementach:

wprowadź opis zdjęcia tutaj

Źródło: czy mogę korzystać

Moglibyśmy więc powiedzieć, że nie ma już powodu do korzystania <object>.

Jednak wciąż ma swoje zalety :

  • Podczas inspekcji (np. Z Chrome Dev Tools) wyświetlany jest cały znacznik SVG na wypadek, gdybyś chciał go nieco zmodyfikować i zobaczyć zmiany na żywo.

  • Zapewnia bardzo solidną implementację rezerwową w przypadku, gdy twoja przeglądarka nie obsługuje plików SVG (poczekaj, ale każda z nich działa!), Co również działa, jeśli SVG nie zostanie znaleziony. To była kluczowa cecha specyfikacji XHTML2, która jest jak betamax lub HD-DVD

Ale są też wady :

ffflabs
źródło
3

Znaleziono jedno rozwiązanie z czystym CSS i bez podwójnego pobierania obrazu. Nie jest tak piękne, jak chcę, ale działa.

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

Chodzi o to, aby wstawić specjalny plik SVG w stylu rezerwowym.

Więcej szczegółów i proces testowania można znaleźć na moim blogu .

Artru
źródło
0

Ta funkcja jQuery przechwytuje wszystkie błędy w obrazach svg i zastępuje rozszerzenie pliku innym rozszerzeniem

Otwórz konsolę, aby zobaczyć błąd podczas ładowania obrazu 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
źródło
-1

Polecam użycie kombinacji

<svg viewBox="" width="" height="">
<path fill="#xxxxxx" d="M203.3,71.6c-.........."></path>
</svg>
Grv97
źródło
czy mógłbyś wyjaśnić, dlaczego użyjesz tych ustawień i dlaczego różni się od innych odpowiedzi?
kvantour
-1

Możesz wstawić SVG pośrednio za pomocą <img>znacznika HTML, a jest to możliwe w StackOverflow zgodnie z poniższym opisem:

Mam następujący plik SVG na moim komputerze

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

Przesłałem ten obraz na https://svgur.com

Po zakończeniu przesyłania otrzymałem następujący adres URL:

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

Następnie RĘCZNIE (bez użycia ikony OBRAZ) dodałem następujący znacznik HTML

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

a wynik jest tuż poniżej

Dla użytkowników z pewnymi wątpliwościami można zobaczyć, co zrobiłem w edycji po odpowiedzi na StackOverflow wstawiając obraz SVG

UWAGA-1: plik SVG musi zawierać <?xml?>element. Na początku po prostu utworzyłem plik SVG, który zaczyna się bezpośrednio od <svg>znacznika i nic nie działa!

UWAGA-2: na początku próbowałem wstawić obraz za pomocą IMAGEikony Edit Toolbar. Wklejam adres URL mojego pliku SVG, ale StackOverflow nie akceptuje tej metody. <img>Etykieta musi być dodany ręcznie.

Mam nadzieję, że ta odpowiedź może pomóc innym użytkownikom.

schlebe
źródło