SVG в HTML: векторная графика

Векторная графика прямо в разметке: иконки, схемы и иллюстрации, которые не пикселят при любом масштабе.

SVG (Scalable Vector Graphics) — это XML-формат векторной графики: вместо пикселей картинка описана фигурами и линиями, поэтому масштабируется без потери чёткости и может жить прямо внутри HTML.

Растровая картинка (PNG, JPEG) — это сетка пикселей: увеличил — и видишь «лесенку». SVG устроен иначе: он хранит инструкции рисования — «нарисуй круг радиусом 40 здесь, проведи линию туда». Браузер каждый раз перерисовывает фигуру под текущий размер, поэтому иконка одинаково резкая и на телефоне, и на 4K-мониторе. А поскольку SVG — это текст-разметка, его можно вставить прямо в страницу и управлять им как обычными элементами.

Зачем это знать на практике

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

Два способа подключить SVG

Первый — как обычную картинку через <img>:

<img src="chart.svg" width="300" alt="График продаж">

Так SVG ведёт себя как чёрный ящик: кешируется как файл, но изнутри его не достать — нельзя перекрасить отдельную фигуру из CSS страницы. Второй способ — inline SVG, когда код фигур лежит прямо в HTML:

<svg width="100" height="100" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="tomato" />
</svg>

Inline-вариант тяжелее в разметке, зато открыт: каждую фигуру можно стилизовать из CSS, анимировать и менять скриптом. Выбор простой: повторяющиеся иконки и интерактив — inline; крупная статичная иллюстрация, которую не надо трогать — через <img> (она не раздувает HTML и кешируется отдельно).

Базовые фигуры

SVG рисует в системе координат, где начало (0,0) — левый верхний угол, ось Y направлена вниз. Основные примитивы:

<svg width="220" height="80" viewBox="0 0 220 80">
  <rect x="10" y="10" width="60" height="60" rx="8" fill="steelblue" />
  <circle cx="120" cy="40" r="30" fill="seagreen" />
  <line x1="160" y1="10" x2="210" y2="70" stroke="black" stroke-width="3" />
</svg>

<rect> — прямоугольник (rx скругляет углы), <circle> — окружность с центром cx,cy и радиусом r, <line> — отрезок от точки к точке. Есть ещё <ellipse>, <polygon> и <polyline> для ломаных.

path — универсальная фигура

Любую сложную форму рисует <path> через атрибут d — мини-язык команд: M — переместиться (moveto), L — линия (lineto), C — кубическая кривая Безье, Z — замкнуть контур:

<svg width="120" height="120" viewBox="0 0 120 120">
  <path d="M60 20 L100 100 L20 100 Z"
        fill="gold" stroke="darkorange" stroke-width="2" />
</svg>

Этот d читается так: перейти в точку (60,20) — вершина, провести линию к (100,100), затем к (20,100), замкнуть. Получился треугольник. Иконки из дизайн-инструментов почти всегда экспортируются именно как один-два <path>.

viewBox — сердце масштабирования

Атрибут viewBox="minX minY width height" задаёт внутреннюю систему координат, независимую от реального размера на экране. Это и есть секрет «бесконечной» резкости:

<svg viewBox="0 0 100 100" width="40" height="40">...</svg>
<svg viewBox="0 0 100 100" width="400" height="400">...</svg>

Внутри обоих рисуем в координатах 0–100, а браузер растягивает результат до 40 или 400 пикселей. Можно вообще убрать width/height и задать размер из CSS — фигура подстроится. Без viewBox такого масштабирования не будет, поэтому его ставят почти всегда.

Стилизация через CSS

У inline SVG фигуры красят не только атрибутами, но и из CSS — через свойства fill (заливка), stroke (контур), stroke-width. Это позволяет менять цвет иконки при наведении или под тему сайта без правки самого SVG:

.icon { fill: #555; transition: fill .2s; }
.icon:hover { fill: tomato; }

Особенно удобен ключевое слово currentColor: если у фигуры fill="currentColor", она автоматически принимает цвет текста родителя — иконка «сама» окрашивается в цвет ссылки или кнопки рядом.

Доступность: title и role

Inline SVG для скринридера по умолчанию — пустое место. Если иконка несёт смысл, дайте ей текстовое имя через дочерний <title> и роль:

<svg viewBox="0 0 24 24" role="img" aria-labelledby="t1">
  <title id="t1">Открыть настройки</title>
  <path d="M12 8a4 4 0 1 0 0 8 4 4 0 0 0 0-8z" />
</svg>

<title> внутри SVG — это не всплывающая подсказка, а доступное имя элемента (его читает скринридер). Связка role="img" + aria-labelledby сообщает вспомогательным технологиям, что перед ними картинка с таким названием. Чисто декоративную иконку, наоборот, прячут атрибутом aria-hidden="true", чтобы не засорять озвучку.

Как это работает под капотом

Inline SVG встраивается прямо в дерево документа наравне с обычными элементами: его узлы — это полноценные DOM-ноды, к ним применяется CSS и к ним можно привязать обработчики событий. Браузер не «вставляет картинку», а рисует фигуры на лету, заново при каждом изменении размера, поэтому масштабирование бесплатно по качеству. SVG, подключённый через <img>, наоборот, изолирован: браузер рендерит его в отдельном контексте, внешний CSS и скрипты внутрь не проникают, зато файл кешируется и не раздувает HTML. Это фундаментальный компромисс: открытость и управляемость против изоляции и кеширования.

Частые ошибки

  • Забыть viewBox. Без него SVG не масштабируется корректно: при изменении width фигуры обрезаются или не тянутся.
  • Ждать стилизации от <img src="icon.svg">. CSS страницы не достаёт внутрь такого SVG — перекрасить фигуру не выйдет, нужен inline.
  • Путать <title> SVG с tooltip. Это доступное имя для скринридера, а не подсказка по наведению (для подсказки используют title-атрибут или CSS).
  • Декоративная иконка без aria-hidden. Скринридер пытается её озвучить и сбивает с толку; декор прячут.
  • Сырые угловые скобки. Теги SVG в примерах HTML обязательно экранируют (&lt;/&gt;), иначе разметка ломается.

Итоги

  • SVG — векторная графика в XML: резкая при любом масштабе, лёгкая, текстовая.
  • Через <img> — изоляция и кеш; inline — доступ из CSS/JS и интерактив.
  • Базовые фигуры: <rect>, <circle>, <line>; <path> рисует что угодно командами M/L/C/Z.
  • viewBox задаёт внутреннюю систему координат и даёт «бесконечную» резкость при масштабировании.
  • Доступность: смысловой иконке — <title> + role="img"; декоративной — aria-hidden="true".
Проверьте себя
1. Зачем у тега <svg> почти всегда указывают атрибут viewBox?
AОн задаёт цвет заливки по умолчанию
BОн задаёт внутреннюю систему координат, благодаря которой SVG масштабируется без потери чёткости
CОн включает ленивую загрузку
DБез него SVG не виден в браузере вообще
2. Почему inline SVG можно перекрасить из CSS страницы, а SVG через <img src="icon.svg"> — нет?
Aimg-версия всегда чёрно-белая
BInline SVG становится частью DOM и к его фигурам применяется внешний CSS, а через <img> SVG изолирован
CCSS вообще не умеет работать с SVG
DДля img нужно добавить атрибут editable
3. Что делает дочерний элемент <title> внутри inline SVG?
AПоказывает всплывающую подсказку при наведении мыши
BЗадаёт доступное имя фигуры, которое читает скринридер
CМеняет заголовок вкладки браузера
DЭто контур для команды path