SVG заметки

Некоторые заметки по работе с <svg> которые вы возможно не знаете и которые будут полезны.

Ресурсы

Иконки (бесплатные):

URL-encoder:

Оптимизация SVG:

Векторизация (Картинка → SVG):

Обязательно ли использовать атрибут xmlns="http://www.w3.org/2000/svg"?

В половине примеров svg, которые я вижу в Интернете, код обернут в простые теги <svg></svg>. В другой половине теги svg имеют множество атрибутов, например:

<svg
	xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink"
	version="1.1"
>

Какие из атрибутов svg действительно нужны?

  • Если вы встраиваете svg код прямо в HTML и при отдаче HTML указан заголовок text/html, то атрибуты xmlns можно не указывать.

    Однако если при отдаче HTML, в который встроен svg код, вы указывает другой тип (заголовок ответа) например image/svg+xml, application/xhtml+xml или любой другой, который заставляет пользовательский агент использовать парсер XML, то атрибуты xmlns обязательны!

    Заметка: Встраивание SVG в HTML-документы стало возможно в HTML5.

    Подробнее: https://stackoverflow.com/questions/18467982/are-svg-parameters-such-as-xmlns-and-version-needed

  • Все браузеры игнорируют атрибут version, поэтому вы всегда можете отказаться от него.

Как наследовать цвет родительского элемента в svg

Есть несколько SVG-изображений, которые нужно вставить в HTML-страницу, стилизованную с помощью CSS. Нужно, чтобы элементы SVG унаследовали цвет от атрибута color родительского HTML-элемента. Варианты: style="fill: inherit" или fill="inherit" не работают.

Проблема тут в том, что HTML использует color, а SVG использует fill и stroke.

Чтобы взять цвет у родительского элемента, можно заставить fill и stroke использовать значение свойства color из CSS. Для этого в CSS есть специальное значение currentColor. fill понимает это значение:

<svg ... fill="currentColor">

ВАЖНО: этот прием будет работать только если SVG встраивается в сам HTML код, а не подключается как файл. Потому что код файла инкапсулирован в самом файле и ничего не знает о внешних данных, а значит currentColor у него ни на что не ссылается.

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

SVG спрайты

Спрайты позволяют объединить несколько svg кодов в один. И затем обращаться к отдельной иконке (svg) не добавляя весь код svg повторно в HTML.

Как создавать спрайт?

Допустим у нас есть две svg иконки:

<svg height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
	<path d="M19 13H5v-2h14v2z"/>
</svg>
<svg height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
	<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</svg>

Чтобы из них сделать спрайт, нужно:

  1. Создать svg элемент (контейнер).

    <svg style="display: none;" aria-hidden="true">
    </svg>
  2. Заменить в исходном коде svg на symbol. А также, добавить атрибут id (по нему в дальнейшем будем обращаться к svg).

    Этот код:

    <svg height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    	<path d="M19 13H5v-2h14v2z"/>
    </svg>

    Переварится в:

    <symbol id="minus" height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    	<path d="M19 13H5v-2h14v2z"/>
    </symbol>
  3. Поместить symbol в контейнер (в спрайт).

    <svg style="display: none;">
    
    	<symbol id="minus" height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    		<path d="M19 13H5v-2h14v2z"/>
    	</symbol>
    
    	<symbol id="plus" height="24px" width="24px" viewBox="0 0 24 24" fill="currentColor">
    		<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
    	</symbol>
    
    </svg>

Теперь можно добавить этот код в HTML, а затем выводить отдельную иконку обращаясь к ней по id:

<svg height="50" width="50"><use xlink:href="#minus"></use></svg>

Или можно создать из этого кода файл, например, sprite.svg и также выводить отдельную иконку обращаясь к ней по id:

<svg height="50" width="50"><use xlink:href="/sprite.svg#minus"></use></svg>

Разница в этих двух подходах, помимо прочего:

  • Когда мы добавляем svg в HTML код страницы, спрайт становится частью DOM дерева и поэтому элементам спрайта можно указать цвет через css или они могут наследовать цвет от родительского элемента - благодаря атрибуту fill="currentColor".

  • А когда, спрайт подключается как файл, файл является внешним элементом и поэтому его элементы никак не связаны с текущим DOM деревом, и им невозможно задать цвет через css или наследовать цвет от родителей.

Поэтому, спрайт лучше подключать прямо в HTML, особенно если спрайт небольшой. Также важно скрыть контейнер, чтобы браузер не пытался его отрисовать. Сделать это можно добавив style="display: none;" к контейнеру.

<svg style="display: none;" aria-hidden="true">
	<symbol id="minus" viewBox="0 0 24 24" fill="currentColor">
		<path d="M19 13H5v-2h14v2z"/>
	</symbol>
</svg>

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

<svg
	aria-hidden="true"
	style="position: absolute; width: 0; height: 0; overflow: hidden;"
	xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink"
>
	<defs>
		<symbol ...>
		<symbol ...>
		<symbol ...>
	</defs>
</svg>

Свойство stroke-dasharray

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

Атрибут stroke-dasharray может быть использован в качестве CSS свойства.

Синтаксис:
// SVG (HTML) атрибут
stroke-dasharray="none | [dasharray]"
// CSS
stroke-dasharray: none | [dasharray];
[dasharray]

Список чисел задающих длину тире и длину пробела. Указывается через запятые или пробелы.

stroke-dasharray="3 1";      // 3 длина тире, 1 длина пробела
stroke-dasharray="3 1, 2 1"; // 3 длина тире, 1 длина пробела, 2 тире, 1 пробел

Можно указать процентные значения:

stroke-dasharray="3 1%"

Если задано нечетное количество значений, то список значений повторяется, чтобы получить четное количество значений. Так 5 3 2 превратиться в 5 3 2 5 3 2:

stroke-dasharray="5 3, 2"

// превратиться в
stroke-dasharray="5 3, 2 5, 3 2"
Пример:
<svg viewBox="0 0 30 10" stroke="tomato" style="width: 10em;">

	<!-- No dashes nor gaps -->
	<line x1="0" y1="1" x2="30" y2="1" />

	<!-- Dashes and gaps of the same size -->
	<line stroke-dasharray="4"  x1="0" y1="3" x2="30" y2="3"/>

	<!-- Dashes and gaps of different sizes -->
	<line stroke-dasharray="4 1"  x1="0" y1="5" x2="30" y2="5"/>

	<!-- Dashes and gaps of various sizes with an odd number of values -->
	<line stroke-dasharray="4 1, 2"  x1="0" y1="7" x2="30" y2="7"/>

	<!-- Dashes and gaps of various sizes with an even number of values -->
	<line stroke-dasharray="4 1, 2 3"  x1="0" y1="9" x2="30" y2="9"/>
</svg>

Получим:

Пример Круговой диаграммы (pie-chart) на SVG с помощью свойства stroke-dasharray:

Еще примеры на codepen: https://codepen.io/tag/stroke-dasharray

Встраивание SVG в CSS

Иногда возникает необходимость вставить SVG-картинку инлайном как значение какого-нибудь свойства в CSS.

Например, иконки как фоновые картинки:

background-image: url('data:image/svg+xml;base64,A1B2...C3=')

Стоян Стефанов напоминает, что почти все браузеры (кроме старых вроде IE), нуждаются в кодировании всего 3 символов: <, > и #. Поэтому делать полноценный base64 не нужно — это не читаемо, не редактируемо, раздувает бандл. Дайте gzip делать его работу.

У Юли Бухваловой есть готовый инструмент под такое:
https://yoksel.github.io/url-encoder/ - преобразует большее количество символов, но зато более надёжно.

Читайте по теме: https://www.phpied.com/truth-encoding-svg-data-uris/