Используем SVG на сайте

a568a437cb904033b72f07018e60caf3.jpg

Оставим за скобками вопрос о целесообразности использования SVG на сайте. Каждый сам для себя должен определить полезность этой технологии. Тем более что эта тема поднималась уже неоднократно.

Сейчас мы рассмотрим методы встраивания SVG, их плюсы и минусы, а так же возможности манипулирования элементами SVG.

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

Иконочный шрифт IMG, background-image Object Inline
CSS Манипуляции Частично1 Нет Частично2 Да
JS манипуляции Частично1 Нет Да Да
SVG анимации Нет Да Да Да
Интерактивные SVG анимации Нет Нет Да Да

1 Можно менять цвет, размер, выравнивание и прочее стили обычного текста
2 Стили должны быть прописаны или в самом SVG файле, или подключены внешним стилем в SVG в начале файла:




По правде говоря стили прописанные внутри SVG так же будут работать и при использовании тега IMG или background-image, но в этом нет никакого смысла.

Иконочный шрифт


e09e46ff604449de91cc3ed5b0816a0a.jpg
Пример на codepen.io

Да, из SVG можно создать иконочный шрифт, более того есть свободно распространяемые иконочные шрифты. Но есть ряд серьезных ограничений. Как и любой символ шрифта SVG иконки в шрифте не могут иметь больше одного цвета.
Вот несколько сервисов, на которых можно скачать готовые наборы иконок, или загрузить свои, и создать собственный иконочный шрифт:


Нужно учесть что при создании собственного шрифта нужно преобразовать все объекты в пути. Тэги и атрибуты которые будут пропущены: circle, rect, stroke, stroke-width, fill, fill-rule.
При использовании иконочного шрифта все элементы SVG объекта объединяются в один символ, и взаимодействовать с ним через CSS и JS можно только как с символом шрифта: менять размер при помощи font-size, менять цвет при помощи color, анимировать при помощи CSS animation или JS и прочее.

Плюсы и минусы такого подхода:
  + иконка ведет себя как символ шрифта, и все параметры настраиваются так же через CSS (размер, цвет, выравнивание и прочее);
  + единственный способ работающий в IE 8 без дополнительных манипуляций;
   все элементы SVG файла объединяются в один символ, поэтому управлять им при помощи CSS или JS можно только как единым целым;
   поддерживаются только одноцветные иконки;
   при сбое загрузки шрифта у пользователя либо не отобразятся иконки совсем, либо, при совпадении кодов иконок с символами юникода, отобразятся соответстующие символы.

SVG как OBJECT


12358d2655064085b871dcac6817b422.jpg
К сожалению (или к счастью) codepen и jsfiddle блокируют загрузку внешних object в целях безопасности.
Встраивание выглядит следующим образом:




Объект встраивает элмемент атрибута data наподобие iframe, добавляя внутрь себя разметку подключаемого файла, поэтому к элементам можно обращаться при помощи JS, но не совсем обычным образом:

var object = document.getElementById("’object’"); //получаем элмент object
var svgDocument = object.contentDocument; //получаем svg элемент внутри object
var svgElement = svgDocument.getElementById("some_id_in_svg"); //получаем любой элемент внутри svg
svgElement.setAttribute("fill", "black"); //меняем атрибуты выбранного элемента


Стоит отметить что в CSS стили для SVG элементов отличаются от стандартных, полный список стилей поддерживаемых SVG можно посмотреть тут.
SVG ведет себя не как обычное изображение, его нельзя непропорционально трансформировать, задавая ширину и высоту. Объект внутри будет занимать максимальную площадь и центрироваться в контейнере:

9d4df228fa4a4dea8e379467b41d103c.jpg

Но объект можно трансформировать используя CSS например так:

transform: scale(2, 1);


IE 8 и ниже не поддерживают SVG от слова «совсем» поэтому, если среди пользователей вашего сайта есть эта специфичная аудитория стоит озаботиться проверкой и заменой svg на растровое изображение. Сделать это можно множеством способов, например используя Modernizr добавлять .no-svg класс для body:

if (!Modernizr.svg) {
        $(body).addClass("no-svg”);
}

.no-svg .icon {
        width: 100px;
        height: 100px;
        background-image: url("icon.png”);
}


Плюсы и минусы такого подхода:
  + можно использовать внешний CSS файл для управления стилями;
  + поддерживаются SVG анимации и фильтры;
  + поддерживаются интерактивные анимации;
   для IE 8 и ниже необходима замена на растровое изображение.

SVG в IMG или background-image


4246bc94f20543c59fc8270027c91acb.jpg
Пример на codepen.io

Оба способа встраивания чем-то похожи на встраивание при помощи тэга object, например нельзя менять пропорции изменением ширины и высоты контейнера, но имеют больше ограничений.
Подключаемые в SVG внешние стили не будут работать, обратиться к элементам через JS так же не получится. Интерактивные анимации в SVG тоже не сработают. А проблемы с IE 8 и ниже так же остаются.
Но SVG анимации будут работать, в обоих случаях.
В случае с IMG втраивание выглядит как обычная картинка:




В случае с background-image как обычный блок:

.icon {
        background-image: url("icon.svg");
        width: 90px;
        height: 150px;
}


Так же при помощи background-image можно использовать спрайты, как с png изображениями, а менять размер можно при помощи background-size:

background-size: 90px 150px;


Учитывая что процент людей c экранами device-pixel-ratio которых выше 1 и их устройства не поддерживают svg стремится к нулю (если такие вообще есть), то можно использовать медиа выражения для подключения svg, только для них, а для остальных использовать png версию:

.icon {
        background-image: url("icon.png");
}
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
        only screen and (min--moz-device-pixel-ratio: 1.5),
        only screen and (-o-device-pixel-ratio: 3/2), 
        only screen and (min-device-pixel-ratio: 1.5) {
        .icon {
                background-image: url("icon.svg");
        }
}


Плюсы и минусы этих подходов:
  + поддерживаются SVG анимации и фильтры;
  + в случае с background-image можно использовать SVG спрайты;
   нельзя менять свойства элементов SVG через CSS или JS;
   не поддерживаются интерактивные анимации;
   для IE 8 и ниже необходима замена на растровое изображение.

Inline SVG


a66410a11f3347d297266b25cdd02975.jpg
Пример на codepen.io

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

Например имея набор иконок в SVG файле, можно использовать их повторно простой конструкцией вида:




где some_svg_element_id id элемента внутри исходного SVG файла.

К отдельно взятому элементу можно, например, применять SVG трансформации:




Но если внутри исходного SVG к элементу была применена интерактивная анимация, например по клику, как в демо выше, то при дублировании объекта анимация будет срабатывать на всех элементах одновременно.
SVG анимации и фильтры это тема для отдельной статьи, поэтому ограничусь лишь примером SVG фильтра (подробнее о SVG фильтрах), и примером SVG анимации (подробнее о SVG анимациях).
С обесепечением работоспособности для IE 8 и ниже все несколько сложнее, чем в других вариантах. Необходимо добавить дополнительную разметку:

if (!Modernizr.svg) {
        $(body).addClass("no-svg”);
}

.no-svg .my-svg-alternate {
        display: block;
        width: 100px;
        height: 100px;
        background-image: url(image.png);
}


Плюсы и минусы этого подхода:
  + никакой подгрузки внешних файлов;
  + доступны манипуляции с элементами SVG через CSS и JS;
  + поддерживаются SVG анимации и фильтры;
  + поддерживаются интерактивные анимации;
  + возможность повторного использования элементов;
   загрязняется код страницы;
   для IE 8 и ниже необходима дополнительная разметка, и замена на растровое изображение.

Заключение


Каждый из способов хорош по своему, и в зависимости от обстоятельств можно использовать любой из них.
Эта статья в первую очередь мой путь по освоению нюансов SVG, и надеюсь многим она будет так же полезна.
P.S. Всем добра и котиков.

© Habrahabr.ru