Структура SVG-файла

ViewBox
Тег <g>
Теги <title> и <desc>
Тег <use>
Тег <symbol>
Тег <path>
CSS
JavaScript

SVG представляет собой обычный XML-файл, который можно просмотреть любым текстовым редактором. Если открыть любой такой файл, созданный в старой версии Adobe Illustrator, то можно увидеть следующее.


<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . 
SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 500 500" enable-background="new 0 0 500 500" 
     width="500" height="500"
     xml:space="preserve">
<!-- Здесь уже сам код  -->
</svg>

Здесь много лишнего кода, который добавил векторный редактор. Его можно безболезненно удалить.

Минимальный код может быть таким.


<svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    viewBox="0 0 500 500">
    <!-- SVG code here  -->
</svg>

В первой строке размещается корневой элемент svg с указанием пространство имён. Далее внутри него идут различные теги. XML позволяет создавать любые теги, но "непонятные" будут игнорироваться. Содержимое файла должно находиться в Unicode-кодировке, но браузер знает об этом, поэтому эту информацию можно убрать из файла (см. первый пример).

Файл поддерживает комментарии, как и HTML-код. Вы также их можете удалять для уменьшения размера.

DOCTYPE также можно убрать по желанию. Мы так и сделали.

А вся важная информация находится в теге svg. У него есть атрибуты, а тег также может содержать дочерние элементы.

За свою историю SVG поменяла несколько версий, начиная с номера 1.0 в 1999 году, затем в 2001 появилась версия 1.1. Некоторые редакторы могут использовать другие версии, которые является частью версии 1.1. Лучше удалить эту информацию, чтобы браузер сам определял версию по умолчанию.

Атрибут id добавлен иллюстратором. Он может пригодится, если вы используете CSS и JavaScript. В других случаях можно удалить.

Атрибуты x и y также нам не понадобятся. Удаляем.

Атрибут enable-background служит для указания фона, но браузер не поддерживает его. Поэтому можно удалить.

Атрибуты width и height также можно удалить в большинстве случаев.

Атрибут xml:space="preserve" не поддерживается браузерами. Значит и его удаляем.

Чтобы вручную не удалять кучу мусора из файла, воспользуйтесь готовым онлайн-инструментом SVGOMG - SVGO's Missing GUI

Последние версии Illustrator и Sketch создают достаточно чистый SVG. У Inkscape при сохранении также есть опция Plain SVG в выпадающем списке поддерживаемых форматов.

Поговорим о других важных атрибутах.

Выше уже упоминалось о пространстве имён, которое указывается в атрибуте xmlns. Данный атрибут позволяет избежать конфликта с языком разметки HTML или другими XML-документами. В частности, SVG может использовать собственные теги title, который используется в HTML только один раз в области head. Адрес http://www.w3.org/2000/svg, указанный в пространстве имён является идентификатором для браузера, в реальности такого адреса нет.

Также указывается ещё одно пространство имён xmlns:xlink="http://www.w3.org/1999/xlink" для избежания конфликта с ссылками HTML href.

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


<a xlink:href="http://blablalba.com">
    <path d"…" />
</a>

Можно создать ссылку на другой фрагмент файла и использовать его в качестве идентификатора. Например, часто используется в теге use. В следующем примере значок, заданный в теге symbol используется далее в другом месте как отдельный элемент.


<svg class="icon" aria-label="CodePen" width="50" height="50">
        <title>Codepen</title>
        <use xlink:href="#codepen" />
    </svg>
</a>
…
<svg style="display: none;">
    <symbol id="codepen" viewBox="0 0 50 50">
        <path d="…"/>
    </symbol>
</svg>

Векторные редакторы могут вставлять свои собственные пространства имён. Например, Inkscape вставляет следующее.


xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
inkscape:version="0.91 r13725"
sodipodi:docname="drawing.svg"

Для использования на веб-странице эти записи можно удалить для уменьшения размера файла.

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

Разрабатывается новая версия SVG 2, где произошли некоторые изменения. В частности можно использовать чистые ссылки HTML.


<a href="http://blablalba.com">
    <path d"…" />
</a>

Но на данный момент браузеры не поддерживают новую версию, поэтому применять ещё рано.

Атрибуты width, height, preserveAspectRatio и viewBox определяют холст для создаваемой графики.

ViewBox

Следующий важный атрибут - это viewBox. Ему мы посвятим отдельную статью.

Тег <g>

Элемент <g> используется для логической группировки набора связанных графических элементов. Это можно сравнить с группировкой объектов в графических редакторах. Он объединяет в группу всё свое содержимое. Как правило, ему задается идентификатор, по которому будет производиться обращение в дальнейшем. Любые стили, применяемые к элементу <g>, будут также применены ко всем его потомкам. Это позволяет задавать стили и преобразования, а также добавлять интерактивность и анимацию сразу целой группе объектов.

В качестве примера будем использовать нарисованную в SVG птичку. Она состоит из нескольких отдельных фигур, описываемых кругами и путями.

В примере помимо общей группы для всей птички (id="bird") выделены также подгруппы, определяющие отдельно голову и тело (id="body", id="head").

Если вы измените цвет заливки группы #body, изменится заливка всех элементов внутри группы. Это может быть очень удобно.


<svg viewBox="0 0 300 200">
	<style>
		svg{background-color:white;}
		#wing{fill:#81CCAA;}
		#body{fill:#B8E4C2;}
		#pupil{fill:#1F2600;}
		#beak{fill:#F69C0D;}
		.eye-ball{fill:#F6FDC4;}
	</style>
	<g id="bird">
		<g id="body">
			<path d="M48.42,78.11c0-17.45,14.14-31.58,31.59-31.58s31.59,14.14,31.59,31.58c0,17.44-14.14,31.59-31.59,31.59S48.42,95.56,48.42,78.11"/>
			<path d="M109.19,69.88c0,0-8.5-27.33-42.51-18.53c-34.02,8.81-20.65,91.11,45.25,84.73c40.39-3.65,48.59-24.6,48.59-24.6S124.68,106.02,109.19,69.88"/>
			<path id="wing" d="M105.78,75.09c4.56,0,8.84,1.13,12.62,3.11c0,0,0.01-0.01,0.01-0.01l36.23,12.38c0,0-13.78,30.81-41.96,38.09c-1.51,0.39-2.82,0.59-3.99,0.62c-0.96,0.1-1.92,0.16-2.9,0.16c-15.01,0-27.17-12.17-27.17-27.17C78.61,87.26,90.78,75.09,105.78,75.09"/>
		</g>
		<g id="head">
			<path id="beak" d="M50.43,68.52c0,0-8.81,2.58-10.93,4.86l9.12,9.87C48.61,83.24,48.76,74.28,50.43,68.52"/>
			<circle class="eye-ball" cx="72" cy="71.5" r="11"/>
			<circle id="pupil" cx="72" cy="71.5" r="7"/>
			<circle class="eye-ball" cx="77" cy="74" r="5"/>
		</g>
	</g>
</svg>

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

Так, в случае со сгруппированной птицей можно масштабировать её всего одной строкой CSS:


#bird {transform: scale(2);}

Группировка добавляет удобств при реализации интерактивности. Вы можете повесить события мыши на всю птицу целиком и заставить ее реагировать также целиком. Это куда удобнее, чем проделывать то же самое для каждого элемента в отдельности.

Теги <title> и <desc>

Элемент <g> имеет еще одну важную и интересную особенность: он может содержать теги <title> и <desc>, которые позволят изображению быть обработанным Читалками (Программы воспроизведения текста для людей с ограниченными возможностями), также они позволяют сделать код более читаемым для человека. Пример использования:


<g id="bird">
	<title>Bird</title>
	<desc>An image of a cute little green bird with an orange beak.</desc>
	<!-- ... -->
</g>

Тег <use>

<use> – инструмент клонирования SVG элементов. С его помощью можно дублировать существующие и заданные элементы. Также данный инструмент предоставляет возможность изменять созданные копии.

Элемент <use> принимает в качестве атрибутов координаты x и y, высоту (height), ширину (width) и ссылку на исходный элемент (xlink:href). В качестве ссылки выступает идентификатор объекта.

Допустим, у нас есть SVG-элемент с заданным идентификатором.


<circle cx="50" cy="50" r="10" fill="red" id="red_circle" />

С помощью <use> данный элемент можно скопировать:


<use xlink:href="#red_circle" />

В корневом SVG-элементе необходимо объявить пространство имен xlink, чтобы ссылка работала.

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


<use xlink:href="#red_circle" fill="blue" />

Дубликат будет иметь красный цвет, а не синий, так как атрибут fill изначально задан в исходном элементе.

Но в копию вполне можно добавить новый атрибут, которого нет в оригинале:


<use xlink:href="#red_circle" stroke="green" stroke-width="5" />

Дубликат так и останется красного цвета, но у него появится зелёный контур.

Пример для птички. Например, если мы хотим добавить еще одну птичку, вместо копирования ее кода можно использовать тег <use>:


...
    <use x="100" y="100" xlink:href="#bird" />
</svg>

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

Допустим, наша птичка была создана в отдельном файле animals.svg. В этом случае ссылаться на нее можно так:


<use x="100" y="100" xlink:href="path/to/animals.svg#bird" />

Координаты, задаваемые элементу <use> отсчитываются не от начала координат всего SVG-изображения. На самом деле это сокращенная форма записи атрибута transform. Следующие две строчки являются эквивалентными:


<use x="100" y="100" xlink:href="#bird" />
<use xlink:href="#bird" transform="translate(100, 100)" />

Проще говоря, координаты задаются относительно исходного элемента. Такое поведение не всегда оптимально и может быть недостатком.

Другим недостатком <use> является то, что копии будут использовать те же стили, что и исходный элемент. При применении стилей или преобразований к группе #bird эти стили и преобразования будут распространяться на все ее копии.

Однако вы все-таки можете применить независимое преобразование к элементу <use>. Например, следующая строка кода позволяет повторно использовать птичку, размеры которой будут составлять лишь половину от размеров исходной:


<use x="100" y="100" xlink:href="#bird" transform="scale(0.5)" />

При этом принцип работы системы координат может показаться несколько неожиданным. Она также масштабируется. Если исходный элемент был спозиционирован в 100 пикселях от края изображения, то такая его копия будет расположена в 50 пикселях от края. На задаваемые x и y это тоже распространяется. Таким образом, слова о расположении копии относительно исходного элемента не совсем верны.

В отличие от преобразований, переопределить стили копии нельзя. Таким образом, если вы захотите создать армию птичек разного цвета, то использовать для этого <use> не получится (если только исходный элемент не определен внутри <defs> без своих стилей, но об этом в следующем разделе).

Элемент <use> позволяет повторно использовать элемент, который уже отображается на SVG-изображении. Если же вы хотите просто определить элемент, не отображая его, а затем отрисовать в нужном месте, когда это потребуется, на помощь придет элемент <defs>.

defs

Чтобы избежать проблемы со свойствами, которые мы хотим переопределить, используют тег <defs>. В таком случае все атрибуты оригинала не будут передаваться на его клон.

Храниться в <defs> может что угодно, начиная с группы элементов, вроде нашей птички, и заканчивая маской или градиентом. Это шаблон для дальнейшего использования. Сам по себе он никогда не отображается, только использующие его сущности.


<defs>
    <circle id="parent_circle" r="20"/>
</defs>

Всё, что описано в теге defs, не будет отрисовано в SVG; заданные элементы будут показываться только через ссылки. Теперь добавим клону атрибуты, которых нет у оригинала:


<use x="70" y="20" xlink:href="#parent_circle" fill="red"/>

Мы создали первый видимый круг. Радиус круга равен 20, что унаследовано от оригинала, но в то же время у него своя позиция и цвет. Можно создать еще один дубликат, просто скопировав тег use:


<use x="70" y="60" xlink:href="#parent_circle" fill="yellow"/>

<svg width="100" height="120" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
      <circle id="parent_circle" r="20"/>
  </defs>
 
  <text y="20">Red</text>
  <use x="70" y="20" xlink:href="#parent_circle" fill="red"/>
  <text y="60">Yellow</text>
  <use x="70" y="60" xlink:href="#parent_circle" fill="yellow"/>
  <text y="100">Green</text>
  <use x="70" y="100" xlink:href="#parent_circle" fill="green"/>
</svg>
Red Yellow Green

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


<svg><use x="0" y="0" xlink:href="#some_svg_element_id" /></svg>

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

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


<svg><use x="0" y="0" xlink:href="#some_svg_element_id" transform="scale(0.5)" /></svg>

Пример (Codepen)

Cat Cat icon

Щёлкните по большому коту

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

Через ссылки можно клонировать не только элементы, также можно создавать целые группы элементов. Группе необходимо присвоить идентификатор, после чего ее можно копировать сколь угодно много раз:


<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
  viewBox="0 0 100 100" 
  width="500" height="200">
<defs>
    <g id="ball_group">
        <circle cx="20" cy="50" r="30" fill="red" />
        <circle cx="70" cy="60" r="40" fill="blue" />
    </g>
</defs>
    <use xlink:href="#ball_group" />
</svg>

Тег <symbol>

Элемент <symbol> похож на <g>: он также предоставляет возможность группировать элементы. Можно выделить два основных отличия:

Элемент <symbol> не отображается сам по себе. Этим он похож на <defs>.

Элемент <symbol> может иметь собственные атрибуты viewBox и preserveAspectRatio. Это позволяет ему уместиться в области просмотра (viewport) так, как этого хотите вы, а не как это определено по умолчанию.

В большинстве случаев <symbol> подходит для определения повторно используемых элементов (символов). Он все так же служит шаблоном для <use>. А имея собственные атрибуты viewBox и preserveAspectRatio, он может растягиваться на прямоугольную область просмотра, задаваемую в ссылающемся на него элементе <use>. Учтите, что элементы <symbol> определяют новую область просмотра каждый раз, когда вызываются элементом <use>.

Это особенность элемента <symbol> позволяет определять элементы, не зависящие от области просмотра, в которую они попадут. Они будут всегда отображаться заданным образом.

Тег <path>

Тег <path> позволяет рисовать комбинацию линий и кривых. Смотрите описание SVG. Path.

CSS

Мы можем указать свойства SVG непосредственно у элемента в коде HTML без CSS. Применим свойства fill и stroke для элемента rect:


<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" viewBox="0 0 200 100">
    <rect x="4" y="4" width="190" height="90" fill="royalblue" stroke="tomato" stroke-width="4"/>
</svg>

Мы также можем добавлять стили с помощью атрибута style. Перепишем пример. Также добавим поворот с помощью свойства CSS3 transform:


<svg xmlns="http://www.w3.org/2000/svg" width="300" height="270" viewBox="0 0 300 270">
    <rect x="95" y="4" width="190" height="90" 
    style="fill:royalblue; stroke:tomato; stroke-width:3; transform: rotate(40deg);"/>
</svg>

Другие примеры использования CSS.

JavaScript

SVG поддерживает JavaScript, но с определёнными условиями. Сценарий должен находиться между тегами svg. Обычно его размещают в самом конце документа, чтобы избежать блокировки загрузки контента. Указывать тип сценария не обязательно, браузеры поймут значение по умолчанию.

Чтобы браузеры не путали сценарий в SVG с сценариями на странице, рекомендуется добавить символ комментария перед [CDATA].


<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
    <script>//<![CDATA[
        …code…
    //]]>
    </script>
</svg>

Можно обращаться к внешним сценариям через xlink:


<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <script xlink:href="external.js" />
</svg>

SVG является XML-документом, а не HTML-документом. Поэтому сценарий не должен использовать методы, связанные с DOM, например innerHTML и т.п. В остальном, всё как обычно.

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

Дополнительные материалы

Namespaces Crash Course - SVG | MDN

Вернуться в раздел SVG

Реклама