Использование SVG

SVG - формат векторной графики. Буквально его название значит «масштабируемая векторная графика» (Scalable Vector Graphics). Попросту говоря, это то, с чем вы работаете в Adobe Illustrator. SVG можно легко использовать в вебе, но сперва нужно во многом разобраться.

Зачем вообще нужен SVG?

Создадим изображение SVG, с которым будем работать дальше

Создайте произвольный рисунок в Adobe Illustrator. Вот, например, птица киви на овале.

Птица киви

Обратите внимание, что изображение кадрируется чётко по краям изображения. Холст в SVG играет не меньшую роль, чем в PNG или JPG.

Adobe Illustrator умеет сохранять в SVG.

Сохранение

При сохранении появится ещё одно диалоговое окно с настройками. Честно говоря, я не очень в них разбираюсь. Существует целая инструкция по Профилям SVG. Меня вполне устраивает SVG 1.1.

Настройки

Здесь стоит отметить, что у вас есть возможность нажать OK и сохранить файл или же нажать кнопку “SVG Code…”, которая откроет окно TextEdit (по крайней мере на Mac) с SVG-кодом.

SVG-код

Оба варианта могут пригодиться.

Добавляем SVG на страницу с помощью тега <img>

Если сохранить изображение SVG в файл, то его можно вставить с помощью тега <img>.

<img src="kiwi.svg" alt="Киви на овале">

В Illustrator рабочая область была размером 612px ✕ 502px.

Рабочая область

Именно такие размеры будут у изображения на странице, если их не указать специально. Его размеры можно изменить, задав атрибуты width или height для img, так же как для PNG или JPG. Вот пример:

Посмотрите на этот пример!

Поддержка браузерами

SVG по-разному поддерживается браузерами. Он работает везде, кроме IE до 8 версии и браузерах на Android до версии 2.3.

Если вы хотели бы использовать SVG, но проект поддерживает браузеры, которые не могут вставлять его через img, есть разные варианты. Я описал некоторые приемы в нескольких своих мастер-классах.

Один из вариантов: проверка поддержки через Modernizr и замена src для изображения:

if (!Modernizr.svg) {
  $(".logo img").attr("src", "images/logo.png");
}

Дэвид Бушел (David Bushell) предложил очень простой альтернативный вариант, если вы не имеете ничего против JavaScript в разметке:

<img src="image.svg" onerror="this.onerror=null; this.src='image.png'">

Еще можно использовать SVGeezy. Далее мы рассмотрим другие способы деградации.

Добавляем SVG через background-image

Использовать SVG в качестве фона c помощью CSS-свойства background-image так же просто, как и вставка с помощью тега img.

<a href="/" class="logo">
  Kiwi Corp
</a>

.logo {
  display: block;
  text-indent: -9999px;
  width: 100px;
  height: 82px;
  background: url(kiwi.svg);
  background-size: 100px 82px;
}

Обратите внимание, что для селектора .logo задан размер background-size. Это необходимо, иначе будет видна только верхняя левая часть изображения SVG, у которого исходный размер намного больше. Эти размеры прописаны с учётом соотношения сторон изображения в оригинале. Можно также использовать для background-size значение contain, чтобы убедиться в том, что изображение поместится в родительский контейнер, если вам не известно какого размера оно должно быть.

Поддержка браузерами

Вставка SVG через свойство background-image по-разному поддерживается браузерами, но в общем дела обстоят так же, как и с img. Проблемой являются IE до 8 версии и браузеры на Android до версии 2.3.

В этом случае нам может помочь Modernizr, даже более эффективно, чем при использовании img. Если заменить background-image на изображение, формат которого поддерживается, на сервер будет отправлен один HTTP-запрос, а не два. Modernizr добавляет класс “no-svg” для html-элемента, если SVG не поддерживается:

.main-header {
  background: url(logo.svg) no-repeat top left;
  background-size: contain;
}

.no-svg .main-header {
    background-image: url(logo.png);
}

Общая проблема при использовании <img> и background-image

Проблема состоит в том, что вы не можете управлять внутренностями SVG с помощью CSS так, как сможете при использовании двух приёмов описанных ниже. Читайте дальше!

Добавляем SVG непосредственно в документ

Помните, как при необходимости можно получить SVG-код прямо при сохранении изображения в Illustrator? Ещё можно просто открыть SVG-файл в текстовом редакторе и скопировать его код. Этот код можно вставить прямо в HTML-документ, и SVG-изображение будет отображаться точно так же, как если бы его вставили с помощью тега img.

<body>

   <!-- вставьте код SVG, и появится изображение! -->

</body>

Этот приём может быть полезным, так как изображение встроено прямо в документ, и для его загрузки не происходит дополнительный HTTP-запрос. У этого метода те же преимущества, как и у использования Data URI. И недостатки у него те же, не обольщайтесь. Среди них: вероятность получения очень тяжелого документа, наличие блоков SVG-кода в нем и невозможность кэширования.

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

<?php include("kiwi.svg"); ?>

Сначала оптимизируем

Без сомнений, для вас не станет сюрпризом то, что SVG, полученные в Adobe Illustrator, не самые оптимальные. Они содержат DOCTYPE, примечания генератора и прочий мусор. У SVG, в общем, и так небольшой размер, но почему бы не уменьшить его еще больше, если есть возможность? Питер Коллингридж (Peter Collingridge) создал SVG Optimiser, инструмент для онлайн-оптимизации SVG. Загружаете старый файл, скачиваете новый. В своём видео Кайл Фостер заходит ещё дальше и удаляет даже переносы строки в процессе оптимизации.

Если вы еще более суровы, вот вам инструмент на Node JS, с помощью которого можно оптимизировать изображения самостоятельно.

Затем управляем с помощью CSS

Видите, насколько сильно теперь SVG похоже на HTML? Это потому, что они оба не что иное, как XML (теги и всякая всячина внутри). В нашем проекте есть два составляющих элемента, <ellipse> и <path>. Можно просто открыть код и присвоить им классы, как любому другому элементу HTML.

<svg ...>
  <ellipse class="ground" .../>
  <path class="kiwi" .../>
</svg>

Теперь эти отдельные элементы можно контролировать с помощью специального CSS для SVG. Необязательно добавлять CSS в сам SVG, его можно разместить где угодно, даже в файле с глобальными стилями. Обратите внимание, что для элементов SVG есть специальный набор свойств CSS. Например, нельзя использовать background-color, вместо него есть fill. Однако кое-что стандартное тоже можно использовать, например, :hover.

.kiwi {
  fill: #94d31b;
}
.kiwi:hover {
  fill: #ace63c;
}

Более того, в SVG можно использовать фильтры, например размытие:

<svg ...>
  ...
  <filter id="pictureFilter" >
    <feGaussianBlur stdDeviation="5" />
  </filter>
</svg>

И его можно применить из CSS:

.ground:hover {
  filter: url(#pictureFilter);
}

Пример того, что может получиться:

Check out this Pen!

Поддержка браузерами

Добавление SVG непосредственно в документ по-разному поддерживается браузерами, однако все сводится к отсутствию поддержки IE младше 8 и браузерам на Android до версии 2.3 1.

Для этого способа вставки SVG можно использовать следующие приемы деградации:

<svg> ... </svg>
<div class="fallback"></div>

И снова используем Modernizr:

.logo-fallback {
  display: none;
  /* Убедитесь, что размер соответствует размеру SVG */
}
.no-svg .logo-fallback {
  background-image: url(logo.png);
}

Добавляем SVG на страницу с помощью тега <object>

Если по какой-либо причине вариант со вставкой SVG непосредственно в документ вам не нравится (он все же имеет парочку недостатков, например, кэширование практически невозможно), можно подключить SVG-файл используя <object> и сохранить возможность управлять его частями посредством CSS.

<object type="image/svg+xml" data="kiwi.svg" class="logo">
  Kiwi Logo <!-- запасное изображение в CSS -->
</object>

На тот случай, если это не поддерживается, реализуем деградацию, используя класс, который добавляет Modernizr:

.no-svg .logo {
  width: 200px;
  height: 164px;
  background-image: url(kiwi.png);
}

При таком подходе не возникают проблемы с кэшированием, и он поддерживается браузерами лучше, чем другие. Но если использовать внешний файл со стилями или <style> встроенный в документ, CSS-навороты работать не будут, нужно добавить элемент <style> в сам SVG-файл.

<svg ...>
  <style>
    /* специальные CSS-фишки для SVG */
  </style>
  ...
</svg>

Внешние файлы со стилями для SVG, вставленного с помощью <object>

Есть способ добавить в SVG-файл внешний файл со стилями, если это необходимо работы для проекта, кэширования или еще чего-то. Я экспериментально выяснил, что он работает только для SVG-файлов, встроенных в документ с помощью тега <object>. Вот что нужно добавить в SVG-файл перед открывающим тегом <svg>:

<?xml-stylesheet type="text/css" href="svg.css" ?>

Если попробовать добавить этот код в HTML, вы получите ошибку, и браузер даже не подумает его подгружать. Если подключить SVG-файл, в котором предложенный код заменяет <img> или background-image, система ругаться не будет, но и работать такой код не будет (SVG, однако, отобразится).

Использование Data URI для SVG

SVG-файл можно уменьшить еще сильнее, если конвертировать его в Data URI. На Mobilefish.com для этого есть онлайн-конвертер. Просто скопируйте содержимое SVG-файла и заполните форму, результат конвертирования можно будет скопировать с текстового поля. Не забудьте удалить переносы строки в полученном коде. Выглядеть он будет как полнейшая тарабарщина:

Data URI

Его можно использовать в любом из приёмов, которые мы рассмотрели (кроме вставки <svg> непосредственно в документ, поскольку это попросту нелогично). Просто скопируйте всю полученную тарабарщину вместо [data] в следующих примерах.

Добавление на страницу с использованием тега <img>

<img src="data:image/svg+xml;base64,[data]">

Добавление на страницу в качестве фона с использованием CSS

.logo {
  background: url(data:image/svg+xml;base64,[data]);
}

Добавление на страницу с использованием тега <object>

<object type="image/svg+xml" data="data:image/svg+xml;base64,[data]">
  fallback
</object>

Кстати, если добавить <style> в SVG до кодирования в base64, он будет работать при добавлении на страницу с использованием тега <object>! А для по-настоящему суровых разработчиков компания Filament group предлагает инструмент grunticon, который автоматизирует этот процесс.

Консольные штучки для перекодирования SVG в base64:

Или же Матиас Биненс (Mathias Bynens) предлагает свои приёмы:

Используйте openssl base64 < path/to/file.png | tr -d '\n' | pbcopy или cat path/to/file.png | openssl base64 | tr -d '\n' | pbcopy чтобы пропустить запись в файл и просто скопировать выходные данные в кодировке base64 в буфер без переносов строки.

Материалы для дальнейшего чтения

Нельзя не упомянуть видео Кайла Фостера «Последовательность оптимизации SVG»:

… взгляните также на это видео + слайды.


Примечания

1. Говоря о браузере Android 2.3, вот. Но если вам никак не обойтись без поддержки родного браузера, вот.