SVG в вёрстке
Векторная графика на странице: инлайн-SVG, фигуры и path, спрайты, currentColor, градиенты, маски и анимации иконок.
1. Зачем SVG
SVG — векторный формат: картинка описывается фигурами и линиями, а не пикселями. Она масштабируется до любого размера без потери чёткости, весит байты и может быть стилизована и анимирована прямо в HTML. Иконки, логотипы, диаграммы, иллюстрации и маски — его родная территория.
- идеальная чёткость на любом экране и любом зумме;
- вес — десятки байт против десятков КБ у PNG;
- интерактив и анимация через HTML/CSS/JS;
- доступность:
titleиdescвнутри SVG; - не подходит для фотографий — их оставляем растровым форматам.
2. Как встроить SVG
Способ встраивания определяет, что вы можете с SVG делать. Иконки и анимации обычно подключают инлайн (код прямо в HTML); повторяющиеся элементы — как отдельный файл через img или фоновую картинку CSS.
| Способ | Стилизация/анимация | Когда |
|---|---|---|
| Инлайн (<svg> в HTML) | да, CSS из страницы | иконки, маски, интерактив |
| <img src="icon.svg"> | нет (только внутри файла) | повторяющиеся статичные картинки |
| background: url() | нет (внутри файла) | фоновые иллюстрации |
| <object>/<iframe> | да, но изолированно | редкий случай, обычно не нужен |
<img> не получает стили снаружи файла: цвет из CSS страницы туда не попадёт. Если нужен переключаемый цвет иконки в теме — копируйте код инлайн или используйте currentColor внутри внешнего файла.3. Внутри: viewBox и фигуры
SVG-холст описывается атрибутом viewBox: четыре числа «x y ширина высота» задают систему координат, в которой рисуют фигуры. Меняется размер SVG — масштаб содержимого сохраняется; меняется viewBox — меняется кадр.
<svg width="200" height="100" viewBox="0 0 200 100">
<rect x="10" y="10" width="80" height="30" fill="#2563eb"/>
<circle cx="150" cy="40" r="25" fill="#f59e0b"/>
<path d="M10 80 L190 60" stroke="#16a34a" stroke-width="4"/>
</svg>| Фигура | Параметры | Смысл |
|---|---|---|
| rect | x y width height rx | прямоугольник (rx — скругление) |
| circle | cx cy r | окружность |
| ellipse | cx cy rx ry | эллипс |
| line | x1 y1 x2 y2 | отрезок |
| polygon | points="x,y …" | замкнутый многоугольник |
| path | d="M…" | произвольная форма (главный рабочий конь) |
4. Градиенты и заливки
Заливка задаётся fill, обводка — stroke с шириной и формой концов. Градиент объявляют внутри defs и ссылаются на него из фигур как url(#grad).
<svg viewBox="0 0 200 80">
<defs>
<linearGradient id="grad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#2563eb"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="10" y="10" width="150" height="50" rx="12"
fill="url(#grad)"/>
<circle cx="180" cy="35" r="18"
fill="none" stroke="#2563eb" stroke-width="4"/>
</svg>- fill: none + stroke для контурных иконок;
- stroke-linejoin/stroke-linecap — как выглядят углы и концы;
- linearGradient — по линии, radialGradient — по кругу.
5. currentColor и «одна иконка на все темы»
Специальное значение currentColor заставляет заливку принимать текущий CSS-цвет текста. Это самый удобный способ сделать одну SVG-иконку, которая перекрашивается в тему, в состояние и в цвет кнопки без копий кода.
<!-- в HTML -->
<button class="btn-search">
<svg class="icon" viewBox="0 0 24 24">
<circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M16 16l5 5" stroke="currentColor" stroke-width="2"/>
</svg>
Найти
</button>
/* в CSS — цвет иконки следует за цветом текста */
.icon { width: 20px; height: 20px; }
.btn-search:hover { color: #2563eb; }
.btn-search:hover .icon { /* уже изменился через currentColor */ }6. Спрайты и
Когда на странице десятки одинаковых иконок, каждый инлайн-код — дублирование. SVG-спрайт собирает все иконки в один скрытый символ <symbol>, а страница обращается к ним через <use>.
<svg style="display:none" width="0" height="0">
<symbol id="icon-heart" viewBox="0 0 24 24">
<path d="M12 21s-8-4.8-8-11a4 4 0 0 1 7-2.8A4 4 0 0 1 18 10c0 5.2-6 11-6 11z"/>
</symbol>
</svg>
<!-- использовать можно бесконечно -->
<svg class="icon"><use href="#icon-heart"/></svg>
<svg class="icon icon--active"><use href="#icon-heart"/></svg>- symbol хранит иконку один раз, use её показывает;
- внешний спрайт — отдельный файл sprite.svg +
- у use нельзя менять fill отдельно для экземпляра (наследует — решайте через currentColor);
- пустой title внутри symbol описывает содержимое для скринридера.
7. Адаптивность и aspect-ratio
SVG, у которого задан только viewBox, по умолчанию растёт на всю доступную ширину. Управляет поведением preserveAspectRatio: большинство случаев покрывается значениями xMidYMid meet (вписать) и slice (обрезать, как cover в CSS).
<svg viewBox="0 0 400 200" preserveAspectRatio="xMidYMid meet">
<!-- meet: вписать целиком, по остатку — отступы -->
</svg>
<svg viewBox="0 0 400 200" preserveAspectRatio="xMidYMid slice">
<!-- slice: заполнить область, обрезав по краю -->
</svg>- CSS-размеры задаются через width/height на svg или класс;
- для «резиновой» иконки достаточно viewBox + width/height в CSS;
- object-fit для SVG не нужен — за вписывание отвечает preserveAspectRatio.
8. Маски и clip-path
Обрезка по форме и прозрачные маски — две близкие, но разные вещи. clip-path физически отрезает, mask показывает сквозь SVG-градиент. В CSS clip-path работает и для любых блоков, не только SVG.
<img src="photo.jpg" alt="Фото"
style="clip-path: url(#avatar)">
<svg width="0" height="0">
<defs>
<clipPath id="avatar">
<circle cx="50" cy="50" r="50"/>
</clipPath>
</defs>
</svg>
/* и без SVG: clip-path на простых фигурах */
.avatar-thumb {
clip-path: circle(50% at 50% 50%);
}- clip-path: круг/многоугольник для декоративных вырезов;
- маски (mask) дают плавные переходы прозрачности от градиентов;
- для обычной круглой аватарки хватит border-radius — clip-path не обязателен.
9. Текст в SVG
Текст внутри SVG — вектор, его можно искривлять по пути, растягивать и разворачивать. Но базовая типографика страницы делается HTML-текстом: SVG-текст не индексируется так же, хуже редактируется и не переносится по словам.
<svg viewBox="0 0 200 60">
<rect x="5" y="5" width="190" height="50" rx="10" fill="#fef3c7"/>
<text x="100" y="35" text-anchor="middle" font-size="16">Лендинг готов</text>
</svg>10. Стилизация и интерактив
Инлайн-SVG наследует все возможности CSS: псевдоклассы hover, transition, transform и даже @keyframes для анимации. Части иконки — это просто элементы со стилями.
<svg class="bell" viewBox="0 0 24 24">
<path d="M6 8a6 6 0 0 1 12 0c0 4 1.5 5 1.5 5H4.5S6 12 6 8z" fill="currentColor"/>
<path class="bell-cap" d="M4 16.5h16" stroke="currentColor" stroke-width="2"/>
</svg>
.bell { width: 24px; height: 24px; color: #374151; }
.bell:hover { color: #2563eb; }
.bell:hover .bell-cap { transform: rotate(-12deg); transform-origin: 50% 16px; }- части иконки анимируются отдельно (колпачок, глаза, хвост);
- transition работает для color/fill/stroke/transform;
- SMIL-анимация (
) возможна, но CSS и JS надёжнее и привычнее.
11. Оптимизация SVG
Редакторы и генераторы оставляют в SVG мусор: комментарии, лишние атрибуты, неверные координаты, раздутые префиксы. Библиотеки (svgo, интернет-оптимизаторы) сжимают файл до минимума без потери вида.
# svgo — сжатие при сборке
npx svgo icon.svg
# исходник: 1200 байт → сжатый: 180 байт
# ключевое, что принесёт пользу руками:
# единый viewBox и fill/color на верхнем уровне, а не внутри каждой фигуры- проверяйте: единый viewBox, без лишних групп
без смысла; - SVG-картинка с «дырами»-масками часто весит больше, чем объединённая;
- инлайн-спрайт из 12 иконок переиспользует один код и весит меньше 12 файлов.
12. Чек-лист SVG на странице
Короткий контроль перед публикацией векторного декора.
- иконки — инлайн, с fill: currentColor (темы перекрашиваются);
- повторяющиеся иконки вынесены в спрайт с symbols;
- декоративные svg скрыты от скринридера (aria-hidden или роли), содержательные имеют title/desc;
- у svg заданы width/height (viewBox для масштаба);
- анимации и hover имеют prefers-reduced-motion-вариант;
- файлы прогнаны через svgo или аналогичный оптимизатор.
Что дальше
Курс завершён.