Миторун Студио

Создание оптимизированных SVG иконок, в Figma и в коде

Олег МиторунФото Олег Миторун

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

Создание иконок в векторном редакторе Figma

Фигуры должны содержать как можно меньше точек. Кривые Безье это тоже точки, одна или две.

По возможности нужно избегать того чтобы точки были не целыми числами. Например если точка имеет целые координаты “25 5” то занимает 3 символа, а если точка будет находиться на “24.85278 4.90012” то это уже 15 символов, в 5 раз больше! Соответственно если svg-файл будет содержать такие точки, то он будет весить в несколько раз больше. А еще такой файл неудобней редактировать.

Размер иконки

Выбор размера холста (Frame), в котором будет отрисована иконка, влияет на размер итогового SVG-файла и на удобство рисования. На сайте я использую иконки размером 30х30 пкс, поэтому для начала попробовал нарисовать иконки в таком же размере 30х30, только размер фрейма взял чуть больше – 32х32. Небольшой запас по 1 пкс с каждой стороны может пригодиться при изменении толщины обводки у фигур, а также как отступы до соседних элементов.

Отрисовка иконки в Figma
Создание иконки в Figma

Несмотря на очень упрощённый вид логотипа “vk” некоторые точки и кривые все-таки пришлось установить посередине между пикселями. Это приводит к тому, что в коде SVG такие точки будут записываться как нецелые числа, через точку (например “8.5”). А наличие таких нецелых чисел приводит к лишним символам в коде и раздуванию размера файла.

В нашем случае можно легко избавиться от нецелых чисел – просто увеличиваем размер холста в два раза, до 64х64 пкс. Тогда все “половинные” пиксели превращаются в целые (например было “8.5”, а стало “17” – минус один символ и один байт). В результате этого действия мы сократили размер нашего файла с 278 байт до 271 байта (это 97,48% от первого варианта, минус 2,52%). Для более сложных иконок будет лучше брать ещё больший размер холста, но желательно не более чем 100х100 пкс – иначе в коде появятся трёхзначные числа.

Координатные точки иконки
Координатные точки иконки

Варианты создания иконок

Иконка состоит из двух контуров (круг и логотип vk) и одного-двух цветов (плюс прозрачный цвет). И в редакторе и формате SVG такую иконку можно сделать разными способами и в разных стилях. С заливкой цветом или с обводкой, с двумя или с одной фигурой-элементом, с закруглениями углов и т.д. В зависимости от дизайна и целей может подойти разный вариант.

6 вариантов иконок
6 вариантов иконок
  1. Базовый вариант, на основе которого будут создаваться остальные. Рисуется фигура Круг (Circle) с заливкой синим фоном и сверху фигура Путь (Path) для логотипа “vk” с заливкой белым фоном.

  2. Аналогично первому варианту, только фигура круг заменяется на путь. Для этого можно перейти в режим редактирования фигуры (Edit Object) и внести минимальные изменения. Я немного сместил кривые, а после сохранения файла вернул прежние значения (какие соответствуют кругу).

  3. Контуры круга и логотипа объединяем в один элемент путь. Выделить обе фигуры > ПКМ > Flatten. Далее в режиме редактирования элемента делаем заливку цветом для области между кругом и лого, а сами буквы логотипа делаем прозрачными.

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

  5. Один элемент путь и для круга и для логотипа, без заливки, с чёрной обводкой в 1 пкс.
    Та же ошибка экспорта из фигмы как и в четвёртом варианте.

  6. Один элемент путь и для круга и для логотипа, без заливки, с чёрной обводкой в 1 пкс, добавлено скругление углов.
    Несмотря на то что в фигме это был один элемент путь – после сохранения в SVG получились два элемента для круга и лого отдельно, каждый с дублирующимися атрибутами обводки и скругления.

Оптимизация SVG файлов

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64">
	<circle cx="32" cy="32" r="30" fill="#3476C5"/>
	<path d="M18 20h-8s2 24 26 24v-3l3-4 7 7h8L43 33l11-13h-8L36 32V20h-8v15c-9-3-10-15-10-15z" fill="#fff"/>
</svg>

Примечание: в данном примере для наглядности добавлена бьютификация кода (переносы строк и отступы).

  1. Базовый вариант, на основе которого будут создаваться остальные. Рисуется фигура Круг (Circle) с заливкой синим фоном и фигура Путь (Path) для логотипа “vk” с заливкой белым фоном.

После Figma:

<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="32" cy="32" r="30" fill="#3476C5"/>
<path d="M18 20H10C10 20 12 44 36 44V41L39 37L46 44H54L43 33L54 20H46L36 32V20H28V35C19 32 18 20 18 20Z" fill="white"/>
</svg>

После SVGO и ручного редактирования:

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64">
<circle cx="32" cy="32" r="30" fill="#3476C5"/>
<path d="M18 20h-8s2 24 26 24v-3l3-4 7 7h8L43 33l11-13h-8L36 32V20h-8v15c-9-3-10-15-10-15z" fill="#fff"/>
</svg>

Примечание: удалил атрибут <svg fill="none">.

  1. Аналогично первому варианту, только фигура Круг заменяется на Путь. Примечание: В фигме чтобы перевести фигуру Круг в Путь, недостаточно только нажать на Edit Object, нужно еще внести минимальные редактирования в этом режиме. Я немного сместил кривые, а после сохранения файла вернул прежние значения (какие соответствуют кругу). После Figma:
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M62 32C62 48.5685 48.5685 62 32 62C15.4315 62 2 48.5685 2 32C2 15.4315 15.5685 2 32 2C48.5685 2 62 15.4315 62 32Z" fill="#3476C5"/>
<path d="M18 20H10C10 20 12 44 36 44V41L39 37L46 44H54L43 33L54 20H46L36 32V20H28V35C19 32 18 20 18 20Z" fill="white"/>
</svg>

После SVGO и ручного редактирования:

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64">
<path d="M62 32a30 30 0 11-60 0 30 30 0 0160 0z" fill="#3476C5"/>
<path d="M18 20h-8s2 24 26 24v-3l3-4 7 7h8L43 33l11-13h-8L36 32V20h-8v15c-9-3-10-15-10-15z" fill="#fff"/>
</svg>
  1. Контур и круга и логотипа сделан одним элементом path, синим фоном залита только внутренняя область между кругом и лого, сами буквы логотипа прозрачные. После Figma:
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M62 32C62 48.5685 48.5685 62 32 62C15.4315 62 2 48.5685 2 32C2 15.4315 15.4315 2 32 2C48.5685 2 62 15.4315 62 32ZM18 20H10C10 20 12 44 36 44V41L39 37L46 44H54L43 33L54 20H46L36 32V20H28V35C19 32 18 20 18 20Z" fill="#3476C5"/>
</svg>

После SVGO и ручного редактирования:

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64">
<path d="M62 32c0 17-13 30-30 30S2 49 2 32 15 2 32 2s30 13 30 30zM18 20h-8s2 24 26 24v-3l3-4 7 7h8L43 33l11-13h-8L36 32V20h-8v15c-9-3-10-15-10-15z" fill="#3476C5"/>
</svg>
  1. Два элемента: круг и путь, каждый без заливки, с черной обводкой в 1 пкс. Отличается от первой иконки тем, что у фигур убраны заливки и добавлены обводки толщиной 1 пкс, черным цветом. В этом примере фигма некорректно конвертирует рисунок в SVG-файл, отчего элемент путь вместо простой черной линии в 1 пиксель превращается в сложнейшую фигуру вокруг этой линии с черной заливкой. Мы это легко исправим, заменив координаты пути на вариант из первого примера, а заливку на обводку. После Figma (редактированная версия):
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="32" cy="32" r="29.5" stroke="black"/>
<path d="M18 20H10C10 20 12 44 36 44V41L39 37L46 44H54L43 33L54 20H46L36 32V20H28V35C19 32 18 20 18 20Z" stroke="black"/>
</svg>

После SVGO и ручного редактирования:

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64" fill="none" stroke="#000">
<circle cx="32" cy="32" r="30"/>
<path d="M18 20h-8s2 24 26 24v-3l3-4 7 7h8L43 33l11-13h-8L36 32V20h-8v15c-9-3-10-15-10-15z"/>
</svg>

Примечание: Чтобы получить обводку 1пкс по центру контура круга – фигма сделала радиус круга 29.5пкс! Я вернул радиус 30пкс. Чтобы сделать толще обводку нужно добавить атрибут stroke-width="2" для <svg>.

  1. Один элемент путь и для круга и для логотипа, без заливки, с черной обводкой в 1 пкс. Та же ошибка фигмы как и в четвертом варианте. После Figma (редактированная версия):
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M62 32C62 48.5685 48.5685 62 32 62C15.4315 62 2 48.5685 2 32C2 15.4315 15.4315 2 32 2C48.5685 2 62 15.4315 62 32Z" stroke="black"/>
<path d="M18 20H10C10 20 12 44 36 44V41L39 37L46 44H54L43 33L54 20H46L36 32V20H28V35C19 32 18 20 18 20Z" stroke="black"/>
</svg>

После SVGO и ручного редактирования:

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64" fill="none">
<path d="M62 32c0 17-13 30-30 30S2 49 2 32 15 2 32 2s30 13 30 30zM18 20h-8s2 24 26 24v-3l3-4 7 7h8L43 33l11-13h-8L36 32V20h-8v15c-9-3-10-15-10-15z" stroke="#000"/>
</svg>
  1. Один элемент путь и для круга и для логотипа, без заливки, с черной обводкой в 1 пкс, добавлено скругление углов. Несмотря на то что в фигме это был один элемент путь – после сохранения в SVG получились два элемента для круга и лого отдельно, каждый с дублирующимися атрибутами обводки и скругления. После Figma:
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M62 32C62 48.5685 48.5685 62 32 62C15.4315 62 2 48.5685 2 32C2 15.4315 15.4315 2 32 2C48.5685 2 62 15.4315 62 32Z" stroke="black" stroke-linejoin="round"/>
<path d="M18 20H10C10 20 12 44 36 44V41L39 37L46 44H54L43 33L54 20H46L36 32V20H28V35C19 32 18 20 18 20Z" stroke="black" stroke-linejoin="round"/>
</svg>

После SVGO и ручного редактирования:

<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 64 64" fill="none">
<path d="M62 32c0 17-13 30-30 30S2 49 2 32 15 2 32 2s30 13 30 30zM18 20h-8s2 24 26 24v-3l3-4 7 7h8L43 33l11-13h-8L36 32V20h-8v15c-9-3-10-15-10-15z" stroke="#000" stroke-linejoin="round"/>
</svg>
Вариант иконкиРазмер SVG после экспортаРазмер SVG после оптимизации
1circle fill
path fill
271 byte? byte
(?%)
2path fill
path fill
364 byte? byte
(?%)
3path fill378 byte? byte
(?%)
4circle stroke
path stroke
3 252 byte
(баг)
? byte
(?%)
5path stroke271 byte? byte
(?%)
6path stroke join452 byte? byte
(?%)
7circle stroke fill
path stroke fill
3 387 byte
(баг)
? byte
(?%)

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

Выводы

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

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