Как правильно вставлять SVG?

SVG — это формат векторной графики, дословно: масштабируемая векторная графика. МВГ? SVG! В векторных форматах хранится не само изображение, а инструкция по его построению по точкам и кривым.


В растровых форматах информация о конкретном числе точек изображения плотно упакована в бинарный кирпич. В него бесполезно заглядывать и менять его можно только в редакторах графики.


?PNG
IH?aV
PLTE???????0?
IDAcZ?d???? ?W=
S?3?o;???]P
???IEND?B`?~

Формат SVG тоже можно создавать и менять в редакторах графики, вроде Illustrator, Sketch или Inkscape. Но ещё он текстовый, а значит его можно открыть как HTML или CSS в любом редакторе кода.


<svg width="20">
  <rect fill="#fc0" width="20" height="20"/>
  <line stroke="black" x1="0" y1="0" x2="20" y2="20"/>
</svg>

Я вам больше скажу: SVG — это как отдельная HTML-страница. Когда вы вставляете SVG, вы, на самом деле, вставляете не просто картинку, а целую страницу. Со своей системой координат, вьюпортом, стилями, скриптами и удивительными особенностями.


Стилями и скриптами, Карл! Вот вам и простая картинка.


Если смотреть на SVG как на отдельную страницу — становится понятнее, какой способ вставки вам нужен. Есть четыре основных и у каждого — особенности.


Первый и самый простой — элемент <img> прямо в HTML-коде. Это в принципе самый эффективный способ загрузить любую картинку — браузеры заранее знают по HTML-коду, что она есть и начинают её подгружать.


Минус в том, что в таком SVG не будут работать скрипты и любые попытки взаимодействия с элементами внутри обречены. Файл будет как за стеклом: смотреть можно, а трогать нельзя. Хотя внутри всё остальное прекрасно работает, включая CSS-анимации.


<img src="picture.svg" alt="За стеклом">

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


Второй способ — фоновая картинка в CSS. Причём неважно, зададите вы его элементу, псевдоэлементу или контентом вставите — результат будет таким же, как с <img>: за стеклом, но внутри что-то работает.


.picture {
  background-image: url(picture.svg);
}

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


Третий способ, через <object>, наконец-то выбивает стекло между страницей и внутренностями SVG-файла. Работают скрипты, взаимодействие, анимация — если они описаны внутри SVG. Между тегами <object> можно вставить фолбэк, который покажется, если браузер не говорит на SVG.


<object type="image/svg+xml" data="picture.svg">
  <img src="picture.png" alt="Фолбэк">
</object>

На самом деле, вместо <object> можно даже использовать <iframe>, как если бы вы подключили другую страницу. Но <object> работает лучше и подстраивается под размеры картинки.


За гибкость приходится платить: из-за того, что это уже не просто графика и там можно скриптовать, к такому способу предъявляются другие требования безопасности. Например, картинку с другого домена просто так уже не вставить.


Этот способ подходит, когда вам нужно вставить какую-то интерактивную графику: игрушки, графики и всякое сложное. Достаточно вспомнить, что когда-то через <object> вставлялись Flash-ролики. Спросите у родителей, что это такое.


Четвёртый способ заработал, когда браузеры переписали свои HTML-парсеры по новому стандарту и содержимое SVG-файлов стало можно вставлять прямо на страницу, как любые другие теги.


<h1>Квадрат</h1>
<svg width="20" height="20">
    <rect fill="#fc0" width="20" height="20"/>
</svg>

С таким SVG можно делать то же, что и с обычными HTML-элементами: стили, скрипты — ну, вы сами знаете. Можно, например, менять цвет заливки при наведении и описывать всё в общих стилях.


<style>
  rect:hover {
    fill: #090;
  }
</style>
<svg>
  <rect fill="#fc0"/>
</svg>

Минус в том, что такие картинки не кэшируются отдельно от страницы — хотя это можно обойти через символы и юзы, но это длинная история, мы об этом ещё поговорим отдельно.


SVG гораздо больше, чем просто формат графики — это мы с вами уже поняли. Хотите закопаться глубже? Читайте статьи Сары Суайдан, это пока лучшее, из того, что есть. Все ссылки есть в описании к видео.


В итоге: способов куча и все чем-то хороши. Выбирайте подходящий под ваши задачи, но всегда начинайте с самых простых: <img> и фона, а потом уже усложняйте — если не хватает.


Видеоверсия



Вопросы можно задавать здесь.

Комментарии (7)


  1. pm_wanderer
    15.09.2017 19:30

    А как работает взаимодействие через object?
    Если «стекло разбивается», то значит можно через условный hover менять цвет линий SVG иконки?


  1. Zenitchik
    16.09.2017 00:32
    +4

    У меня де-жа-вю?
    Не далее как позавчера я гуглил эту тему и нашёл вот что https://habrahabr.ru/post/260645/
    Те же четыре способа, только слегка подробнее и в 15 году.


  1. Shtucer
    16.09.2017 01:16
    -1

    Вольф говорит:
    — Недавно прочел «Технологию секса». Плохая книга. Без юмора.
    — Что значит — без юмора? Причем тут юмор?
    — Сам посуди. Открываю первую страницу, написано — «Как правильно вставлять SVG». Разве так можно?»


  1. Hellek
    18.09.2017 10:01

    Ещё можно упомянуть о недостатке inline-вставки, такие svg не кэшируются, и если на странице много сложных изображений, то она будет довольно увесистой


    1. noodles
      18.09.2017 10:48

      gzip по идее это решает, ему только это и подавай)

      как правило svg — это иконки в основном, а если векторная иллюстрация по настоящему сложная — то выгоднее, наверное, переводить в jpeg/png (от задачи зависит конечно же)


  1. Hellek
    19.09.2017 00:39

    Так, постойте. Вот пример, внизу иконки fractal-group.ru/mashinnaya-shtukaturka они вставлены в коде, тут gzip вроде никак не поможет. Пришлось делать такую вставку, чтобы удобно управлять через css издалека.


    1. wixus
      19.09.2017 12:48

      Гзип поможет, но можно и асинхронно подгружать содержимое свг (по атрибуту src у img) и заменять им картинку. Т.е. если JS отключен, то просто ховеров не будет, а если включен, то вместо img загрузится полноценный svg-код и верти его как хочешь.