Чи потрібно використовувати <img>, <об’єкт> або <embed> для файлів SVG?


603

Повинен чи я використовувати <img>, <object>або <embed>для завантаження файлів SVG на сторінку таким чином , схоже на вивантаження jpg, gifабо png?

Який код для кожного, щоб забезпечити його максимальну ефективність? (Я бачу посилання на включення міметипу або вказівку на резервні SVG-рендери в моє дослідження і не бачу хорошого найсучаснішого посилання).

Припустимо, я перевіряю підтримку SVG за допомогою Modernizr і відмовляюся (можливо, я замінюю звичайний <img>тег) для браузерів, які не підтримують SVG.


3
просто подивіться на github.com/jonathantneal/svg4everybody
Machado

2
Теоретично, ви також можете мати, <svg>з якого ви хочете посилатися на інші SVG. Цього можна досягти, наприклад, використовуючи <image>.
phk

Відповіді:


635

Я можу порекомендувати SVG Primer (опублікований W3C), який висвітлює цю тему: http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML

Якщо ви користуєтесь, <object>ви отримуєте растровий запас безкоштовно *:

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

*) Ну, не зовсім безкоштовно, оскільки деякі браузери завантажують обидва ресурси, див. Пропозицію Ларрі нижче про те, як обійти це.

Оновлення 2014 року:

  • Якщо ви хочете неінтерактивний svg, скористайтеся <img>резервними копіями сценарію до версії png (для старих IE та android <3). Один чистий і простий спосіб зробити це:

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

    Це буде вести себе як GIF-зображення, і якщо ваш браузер підтримує декларативні анімації (SMIL), вони відтворюватимуться.

  • Якщо ви хочете інтерактивний svg, використовуйте або <iframe>або <object>.

  • Якщо вам потрібно надати старшим браузерам можливість використовувати плагін svg, тоді використовуйте <embed>.

  • Для svg в css background-imageта подібних властивостях модернізатор - це один вибір для переходу на резервні зображення, інший - залежно від декількох фонів, щоб зробити це автоматично:

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

    Примітка . Стратегія декількох фонів не працює на Android 2.3, оскільки вона підтримує декілька фонів, але не svg.

Додатковим корисним читанням є цей поштовий блог про запаси svg.


7
Який правильний спосіб встановити розмір? Чи включати атрибути по висоті та ширині, чи я використовую CSS?
artlung

5
Використовувати css - це добре, або встановити розмір елемента вбудовування (тобто: iframe, embed, object, img) - те, що останній робить, це може уникнути спалаху невпорядкованого контенту перед таблицею стилів, що визначає розмір завантажується. Також переконайтеся, що у svg є атрибут viewBox, і видаліть атрибути ширини / висоти з кореневого елемента svg. Це дасть вам найкращу поведінку перехресного веб-переглядача.
Ерік Дальстрем

8
Цей метод завжди завантажує растровий файл. Ця відповідь гарантує, що резервний запит запитується лише у застарілих браузерах IE.
Ларрі

3
Зауважте, що вищезгадане не працює з плагіном Adobe SVG. Але ви можете змусити його працювати (сучасні браузери + ASV + MSIE), якщо додати <param name="src" value="your.svg" />всередині <object>тегу. Я витратив дуже довгий час, намагаючись зрозуміти, як все це зробити, і, думаю, нарешті це зрозумів.
Крістофер Шульц

5
Я думаю, що чим швидше люди перестануть підтримувати старовинні браузери, тим швидше у нас з’явиться суспільство, яке постійно оновлює браузери, яке навіть автоматично переходить до браузера з 2012 року. Єдиним приводом може бути відсутність вільного доступу до сучасного браузера, але Firefox наприклад, підтримує Windows XP досі (можливо, до версії 52). ЗАВЖДИ є сучасна та безкоштовна альтернатива.
Неоніт

116

З IE9 і вище ви можете використовувати SVG у звичайному тезі IMG ..

https://caniuse.com/svg-img

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

35
Це не працює, якщо SVG вимагає завантаження інших ресурсів. (Шрифти, зображення, ...)
TheHippo

10
Для логотипу чи піктограми я все-таки рекомендую використовувати тег IMG з семантичних причин і переконайтеся, що SVG є лише векторною ілюстрацією.
Крістіан Ландгрен

4
Зараз прийнято скрізь. @artlung, ви можете змінити свою відповідь на цю.
SteeveDroz

15
Кожен, хто використовує <img/>тег, може захотіти знати про додавання ідентифікаторів фрагмента SVG , наприклад, " <img src="myimage.svg#svgView(preserveAspectRatio(none))" />", що дозволяє контролювати співвідношення сторін viewBoxтощо, так само, як і вбудовані визначення SVG. Подальше читання про масштабування - css-tricks.com/scale-svg
brichins

101

<object>і <embed>мають цікаву властивість: вони дозволяють отримати посилання на документ SVG із зовнішнього документа (враховуючи політику того самого походження). Потім посилання може використовуватися для анімації SVG, зміни його таблиць стилів тощо.

Дано

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

Потім ви можете робити такі речі

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

Я не думаю, що ви отримаєте подію "load" від елемента <object>. Не підтримується.
Стів О'Коннор

5
@ SteveO'Connor Я не знаю, можливо, це недостатньо задокументовано, але це, безумовно, працює у Firefox, IE11 та Chrome. Принаймні, із зовнішніми файлами SVG: я не міг змусити його працювати з URI-адресами даних.
WGH

Чудово працює! Цікаво, що додавання поля 'id' здається необхідним, коли у вас є два SVG-файли, інакше лише 1 з'явиться в моєму оглядачі опери?
Брам

Ви отримуєте найкраще як в прямому, так і в посиланні за допомогою цього методу!
Брандіто

Добре знати, що гіперпосилання всередині SVG не працюватиме, якщо SVG не вбудований.
Менталіст

26

Найкращий варіант - використовувати зображення SVG на різних пристроях :)

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

3
цікаво. але ви впевнені у onerrorпожежах, якщо svg не відображається? які браузери ви протестували?
artlung

1
Так, я
тестую

24

Використовуйте srcset

Більшість сучасних веб-переглядачів сьогодні підтримують srcsetатрибут , який дозволяє вказувати різні зображення різним користувачам. Наприклад, ви можете використовувати його для щільності 1x та 2x пікселів, і браузер вибере правильний файл.

У цьому випадку, якщо ви вкажете SVG у програмі, srcsetа браузер його не підтримує, він буде резервним src.

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

Цей метод має ряд переваг перед іншими рішеннями:

  1. Він не покладається на якісь дивні хаки чи сценарії
  2. Це просто
  3. Ще можна включити текст alt
  4. Веб-браузери, які підтримують, srcsetповинні знати, як з цим впоратися, щоб він завантажував лише потрібний файл.

5
Навіщо турбуватися, враховуючи, що є> 99% шансів, що будь-який браузер підтримає SVG сьогодні?
Роберт Лонгсон

5
Частина від того, щоб КОЖНО кожний міг точно бачити сторінку, Google полюбить вас більше!
Гути

2
Виглядає краще, ніж це, враховуючи, що в даний момент часу ви натискаєте резервне зображення на ~ 10% користувачів.
Волкер Е.

2
@VolkerE. 10%? канюза демонструє відсутність підтримки SVG близько 2% . Я все ще використовую srcset, як у відповіді, хоча для підтримки 2%. В майбутньому, я сподіваюся, що браузери зможуть отримувати інформацію, наприклад, srcset та вибирати відповідне зображення на основі таких факторів, як продуктивність та розмір, а не лише розмір пристрою чи підтримка формату файлів.
Викладач

3
Проблема з цим рішенням є лише тоді, коли браузери підтримують SVG, але не srcset. Наприклад, IE11, який за замовчуванням повертається до PNG, хоча він підтримує SVG
Hego555,

16

Якщо вам потрібні ваші SVG-файли для стилізації CSS, вони повинні бути вбудованими в DOM. Цього можна досягти за допомогою ін'єкції SVG, яка використовує Javascript для заміни елемента HTML (зазвичай<img> елемента) вмістом файлу SVG після завантаження сторінки.

Ось мінімальний приклад використання SVGInject :

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

Після завантаження зображення onload="SVGInject(this)запустить ін'єкцію, і <img>елемент буде замінено вмістом файлу, що міститься в srcатрибуті. Це працює з усіма браузерами, які підтримують SVG.

Відмова: Я є співавтором SVGInject


15

Я особисто використовував би <svg>тег, тому що якщо у вас є повний контроль над ним . Якщо ви все-таки використовуєте це в<img> вас не виходить керувати внутрішніми частинами SVG за допомогою CSS тощо.

інша річ - підтримка браузера .

Просто відкрийте svgфайл і вставте його прямо в шаблон.

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

то у своєму css ви можете просто наприклад:

svg {
  fill: red;
}

Деякий ресурс: поради щодо SVG


15

Якщо ви використовуєте теги <img> , веб-переглядачі на веб-програмах не відображатимуть вбудовані растрові зображення .

Для будь-якого виду розширеного використання SVG, включаючи вбудований SVG, пропонується на сьогодні найбільшу гнучкість.

Internet Explorer і Edge змінять розмір SVG правильно , але потрібно вказати і висоту, і ширину.

Ви можете додати onclick, onmouseover і т. Д. Всередині svg до будь-якої форми у SVG: onmouseover = "top.myfunction (evt);"

Ви також можете використовувати веб-шрифти в SVG, додаючи їх у свій звичайний аркуш стилів.

Примітка. Якщо ви експортуєте SVG з Illustrator, імена веб-шрифтів будуть неправильними. Ви можете виправити це у своєму CSS та уникати возитися у SVG. Наприклад, Illustrator дає неправильне ім’я Arial, і ви можете виправити це так:

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

Все це працює далі будь-якому браузері, випущеному з 2013 року .

Для прикладу дивіться ozake.com . Весь сайт складається з SVG, крім контактної форми.

Попередження: Веб-шрифти в Safari не точно змінені - і якщо у вас є багато переходів від простого тексту до жирного або курсивного, в точках переходу може бути невелика кількість зайвого або відсутнього місця. Дивіться мою відповідь на це запитання для отримання додаткової інформації.


Дякую. Щойно витратив 3 години на витягування волосся, намагаючись з'ясувати, чому растрові зображення не відображаються в моєму imgтезі ... Чи знаєте ви, чи це офіційно десь зафіксовано?
житній хліб

@Andrew Swift, ви отримуєте дійсно хороші візуальні результати на dev.ozake.com , але є серйозні проблеми з доступністю: пошукові системи, ймовірно, будуть важко індексувати сайт (я не впевнений, що вони підберуть посилання, приховані в SVG подіях) ; на сайті не можна переміщуватися за допомогою клавіатури; Мабуть, читачі екрану задихнуться від цього ...
interDist

11

Мої два центи: станом на 2019 рік 93% використовуваних браузерів (і 100% останніх двох версій кожної з них) можуть працювати з SVG в <img>елементах:

введіть тут опис зображення

Джерело: Чи можу я використовувати

Тож ми могли б сказати, що більше немає причин використовувати <object>.

Однак це все ще має свої плюси :

  • Під час огляду (наприклад, за допомогою Інструментів Chrome Dev) вам надається вся розмітка SVG, якщо ви хочете трохи підробити її та побачити зміни в реальному часі.

  • Це забезпечує дуже надійну резервну реалізацію, якщо ваш браузер не підтримує SVG-файли (зачекайте, але кожен з них робить!), Що також працює, якщо SVG не знайдено. Це було ключовою особливістю специфікації XHTML2, яка схожа на betamax або HD-DVD

Але є і мінуси :


3

Знайдено одне рішення з чистим CSS та без подвійного завантаження зображення. Це не красиво, як я хочу, але це працює.

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

Ідея полягає в тому, щоб вставити спеціальний SVG з резервним стилем.

Більш детальну інформацію та процес тестування ви можете знайти в моєму блозі .


0

Ця функція jQuery фіксує всі помилки у зображеннях svg та замінює розширення файлу альтернативним розширенням

Відкрийте консоль, щоб побачити помилку при завантаженні зображення 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

Я рекомендую використовувати комбінацію

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

Ви могли б детальніше пояснити, чому ви використовуєте ці налаштування і чому він відрізняється від будь-яких інших відповідей?
kvantour

-1

Ви можете вставити SVG побічно, використовуючи <img> тегу HTML, і це можливо в StackOverflow, дотримуючись описаного нижче:

У мене на ПК є наступний файл SVG

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

Я завантажив це зображення на https://svgur.com

Після закінчення завантаження я отримав таку URL-адресу:

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

Тоді я МАНУЛЬНО (без використання значка IMAGE) додав наступний тег HTML

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

а результат трохи нижче

Для користувача з деяким сумнівом можна побачити, що я зробив під час редагування наступної відповіді на StackOverflow, що вставляє SVG-зображення

ПАМ’ЯТАЙТЕ-1: файл SVG повинен містити <?xml?>елемент. На початку я просто створив файл SVG, який починається безпосередньо з <svg>тегу, і нічого не працює!

ПАМ’ЯТАЙТЕ-2: на початку я спробував вставити зображення за допомогою IMAGEпіктограми Edit Toolbar. Я вставляю URL-адресу свого SVG-файлу, але StackOverflow не приймає цей метод. The<img>Тег повинен бути доданий вручну.

Сподіваюся, що ця відповідь може допомогти іншим користувачам.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.