Использовать ли <img>, <object> или <embed> для файлов SVG?


603

Должен ли я использовать <img>, <object>или <embed>для загрузки файлов SVG на страницу таким образом , похоже на выгрузку jpg, gifили png?

Какой код для каждого, чтобы он работал как можно лучше? (Я вижу ссылки на включение mimetype или указание на запасные рендеры SVG в моих исследованиях и не вижу хорошего уровня техники).

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


3
просто взгляните на github.com/jonathantneal/svg4everybody
Machado

2
Теоретически, вы также <svg>можете иметь ссылку на другие SVG. Это может быть достигнуто, например, с помощью <image>.
PHK

Ответы:


636

Я могу порекомендовать 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и аналогичных свойствах modernizr - это один из вариантов переключения на резервные изображения, а другой зависит от нескольких фонов, чтобы сделать это автоматически:

    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) - последнее делает то, что он может избежать flash-of-unstyled-content перед таблицей стилей, которая определяет размер загружен. Также убедитесь, что svg имеет атрибут viewBox, и удалите атрибуты width / height из корневого элемента svg. Это даст вам лучшее поведение кроссбраузера в моем опыте.
Эрик Дальстрем

8
Этот метод всегда загружает растровый файл. Этот ответ гарантирует, что запасной вариант запрашивается только в старых браузерах IE.
Ларри

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

5
Я думаю, что чем быстрее люди перестанут поддерживать древние браузеры, тем быстрее у нас будет общество, которое будет поддерживать их браузеры в актуальном состоянии, которое даже автоматически будет работать с браузерами с 2012 года. Единственным оправданием будет отсутствие свободного доступа к современному браузеру, но Firefox например, поддерживает Windows XP (возможно, до версии 52). ВСЕГДА есть современная и бесплатная альтернатива.
Неонит

117

Начиная с IE9 и выше, вы можете использовать SVG в обычном теге IMG.

https://caniuse.com/svg-img

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

35
Это не работает, если SVG требует загрузки других ресурсов. (Шрифты, изображения, ...)
TheHippo

11
Для логотипа или значка я бы по-прежнему рекомендовал использовать тег IMG по семантическим причинам и убедиться, что SVG - это просто векторная иллюстрация.
Кристиан Ландгрен

4
Сейчас принято везде. @artlung, вы можете изменить свой ответ на этот.
SteeveDroz

16
Любой, кто использует <img/>тег, может захотеть узнать об добавлении идентификаторов SVG Fragement , например, " <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 будет отображаться в моем браузере Opera?
Брэм

Вы получаете лучшее из встроенного и ссылочного с этим методом!
Брандито

Хорошо знать, что гиперссылки внутри SVG не будут работать, если SVG не встроен.
Менталист

26

Лучший вариант - использовать SVG Images на разных устройствах :)

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

3
интересно. но вы уверены, что onerrorпожары, если SVG не рендерится? какие браузеры вы тестировали?
artlung

1
Да, я тестирую его на мобильной ОС Android, браузере по умолчанию :)
Роберт Соль

24

использование srcset

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

В этом случае, если вы укажете SVG в srcsetбраузере, а браузер его не поддерживает, он откатится на src.

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

Этот метод имеет несколько преимуществ по сравнению с другими решениями:

  1. Это не полагаться на какие-то странные хаки или скрипты
  2. Это просто
  3. Вы все еще можете включить альтернативный текст
  4. Браузеры, которые поддерживают, srcsetдолжны знать, как с этим обращаться, чтобы он загружал только тот файл, который ему нужен.

5
Зачем беспокоиться, учитывая, что есть вероятность> 99%, что любой браузер будет поддерживать SVG в наши дни?
Роберт Лонгсон

5
Часть из того, что ВСЕ могут видеть страницу точно, Google будет любить вас больше!
Hoots

2
Выглядит лучше, чем сейчас, учитывая, что в данный момент вы отправляете резервное изображение ~ 10% пользователей.
Фолькер Э.

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

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> , то браузеры на основе webkit не будут отображать встроенные растровые изображения .

Для любого вида расширенного использования 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 Tools) вам предоставляется вся разметка SVG на случай, если вы захотите немного подделать ее и увидеть живые изменения.

  • Он обеспечивает очень надежную реализацию в случае, если ваш браузер не поддерживает SVG (подождите, но каждый из них поддерживает!), Что также работает, если SVG не найден. Это была ключевая особенность спецификации XHTML2, которая похожа на betamax или HD-DVD

Но есть и минусы :


4

Нашел одно решение с чистым 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>

Не могли бы вы уточнить, почему вы используете эти настройки и почему они отличаются от любых других ответов?
Квантур

-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 не принимает этот метод. <img>Тег должен быть добавлен вручную.

Я надеюсь, что этот ответ может помочь другим пользователям.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.