Основы работы с SVG

Июнь 18, 2014 ||  css , svg , translation ||  Using SVG  ||  комментарии

SVG это формат векторной графики, буквально означающий Масштабируемая Векторная Графика. Собственно это то с чем вы работаете в Иллюстраторе. SVG использовать в вебе довольно просто но тем не менее есть куча того что необходимо знать.

Зачем это вообще все?

  • Маленький размер который к тому же хорошо сжимается
  • Масштабирование без потери четкости (за исключением очень маленьких размеров)
  • Отлично выглядит на ретине
  • Легко управляем, фильтры, интерактивность

Где взять SVG графику

Нарисуйте что-нибудь в Иллюстраторе, вот к примеру типа такого:

Kiwi

Обратите внимание что картинка обрезана четко по краю изображения. Полотно, или основа, имеет значение в svg точно также как в png или jpg.

Графику в Иллюстраторе можно сохранять как svg файл.

save as

При сохранении есть кучка настроек но я честно говоря особо в них не разбираюсь. На эту тему есть целая спецификация. Сохранение как версия 1.1 работает нормально как по мне.

options

Интересный момент здесь в том что можно либо сохранить файл либо выбрать SVG Code... и при этом откроется текстовый редактор с кодом svg.

code

Оба варианта полезны.

Использование svg как <img>

После сохранения svg файла, его можно напрямую использовать в html.

<img src="kiwi.svg" alt="Kiwi standing on oval">

В иллюстраторе полотно было размером 612 на 502 пиксела.

illustrator

Именно такого размера картинка будет на странице если ей никак не задавать размеры. Можно просто поменять размер точно также как это делается для png или jpeg изменяя width и height.

JS Bin

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

Использование svg в элементе img поддерживают такие браузеры, а точнее - это работает везде кроме Эксплорер 8 и ниже и Андроид 2.3 и ниже.

Если вы хотите использовать svg но также нужно как то поддерживать эти браузеры то есть несколько вариантов. О нескольких разных вариантах я рассказывал на разных семинарах.

Один из вариантов это проверить поддержку SVG при помощи Modernizr и поменять атрибут src.

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

David Bushell предложил очень простую альтернативу, если вас не смущает джаваскрипт код в html:

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

Есть еще такой инструмент - SVGeezy.

SVG как фоновая картинка

Точно также как обычные картинки можно применять svg как фоновую картинку.

<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. Это необходимо, иначе мы увидим только верхний левый фрагмент намного большей исходной svg картинки. Эти размеры должны учитывать соотношение сторон оригинальной картинки. Но не забывайте что можно просто использовать background-size: contain если вы не знаете точных размеров родительского элемента.

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

Использование svg для фоновых картинок имеет похожую на SVG для картинок поддержку. Проблемы только с ИЕ 8 и ниже и андроид 2.3 и ниже.

Опять же modernizr хорошо помогает здесь и даже более эффективно чем с img. Если мы поменяем значение для background-image на поддерживаемый формат то буден сделан только один http запрос вместо двух в предыдущем случае. Модернизер добавляет класс в html - no-svg если браузер не поддерживает формат, и тогда мы можем сделать:

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

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

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

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

Проблема с и с фоновыми картинками

В том что вы не получаете контроля над содержимым SVG по сравнению с следующими двумя способами.

Инлайновый svg

Помните способ получить код svg который мы встречали когда сохраняли svg из иллюстратора? Этот же самый код можно получить просто открыв svg файл текстовым редактором. Так вот можно взять этот код, вставить прямо в html и мы получим ту же самую картинку как если бы вставили элементом img.

<body>

   <!-- paste in SVG code, image shows up!  -->

</body>

Плюс здесь в том что картинка уже находится прямо в документе и не требует никаких http запросов. Другими словами плюсы в этом такие же как при использовании Data URI. И недостатки тоже те же самые. Потенциально раздутый код, здоровая куча хлама прямо в документе который вы редактируете плюс невозможность кеширования.

Если вы пишете на каком нибудь серверном языке то вы можете добиться чистоты как то так:

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

Оптимизация

Наверно вас это не сильно удивит но svg который делает иллюстратор не самый идеальный с точки зрения оптимизации. Поджать можно при помощи SVG Optimiser. Загружаете старый выгружаете новый. В этом видео показываеться что можно даже удалить переносы строк после такой оптимизации.

Если вы реально круты вот вам инструмент для Нода.

И теперь можно контролировать картинку стилями!

Нетрудно заметить что svg выглядит очень похоже на html, это потому что по сути xml документы. Наша конкретная картинка состоит из двух тегов, <ellipse> и <path>. Ничего нам не мешает присвоить элементам классы точно также как мы делаем в html.

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

Теперь мы можем стайлить эти элементы специальным svg css. Эти стили не обязательно должны быть внутри svg, можно даже их выносить в наши обычные стили. Обратите внимание что элементы svg имеют свои специфические css свойства. К примеру вместо background-color надо использовать fill. Обычные штуки типа ховера работают.

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

Что совсем круто так это фильтры в svg. Например размытие. Сначала надо вписать фильтр в svg:

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

Потом это используется в стилях так:

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

JS Bin

Поддержка

У встроенный svg свой набор поддерживаемых браузеров, но, опять же, проблемы с ИЕ8 и андроидом 2.3.

Один способ реализовать совместимость:

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

Дальше при помощи Модернизера:

.fallback {
  display: none;

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

SVG как <object>

Если видеть в html кучу хлама вам не по душе можно залинковать svg файл сохраняя возможность работать с деревом элементов:

<object type="image/svg+xml" data="kiwi.svg" class="logo">
  Kiwi Logo <!-- fallback image in CSS -->
</object>

Для старья опять Модернизер:

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

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

<svg ...>
  <style>
    /* SVG specific fancy CSS styling here */
  </style>
  ...
</svg>

Внешние стили для <object>

Есть способ для указания внешних стилей что есть неплохо для кеширования. Это работает только для <object> содержащими svg файл, по крайней мере мои тесты показали так. Нужно в ваш svg файл поместить вот это перед открытием svg тега.

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

Если вы это вставите в ваш html то страница не срендерится, если это будет в svg но svg вставляется как или как фоновая картинка, страница отрисуется, svg тоже срендерится но стили эти работать не будут.

Data URI

Еще один способ сжать максимально это сконвертировать svg в data uri. Можно это сделать специальным сервисом. Кидаете туда содержимое вашего svg файла и получаете вот такой вот мусор. Не забудьте удалить переносы строк.

svg data uri

Потом это можно вставлять во все варианты о которых мы говорили кроме конечно инлайновый svg, это просто не имеет смысла в данном случае. Этот код должен быть на месте [data]:

Картинка

<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 перед тем как вы конвертировали это по прежнему будет работать в случае использования как <object>.

Полезные инструменты

grunticon

Берет папку с svg/png файлами (иконки сделанные в илюстраторе или типа того), и выводит ее в трех форматах: svg data uri, png data uri и таблицу стилей для совместимости с сылками на обычные картинки, которые тоже генерируются автоматически и выкладываются в отдельную папку.

iconizr

Консольный инструмент (PHP) для конвертирования svg картинок в набор иконок (svg & png, отдельные иконки и / или спрайты) с поддержкой оптимизации и выходного формата в sass.

По теме

comments powered by Disqus