Использование SVG

Кодинг
Q_Time

7 минут чтения

hero image

Содержание

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

Как добавить SVG

Прежде чем анимировать, разберёмся, как SVG попадает на страницу. Способ вставки определяет, что вы сможете с ним делать.

Через тег <img> — самый простой способ. SVG вставляется как обычная картинка: <img src="icon.svg">. Работает, но вы теряете доступ к внутренним элементам. Нельзя менять цвета, анимировать отдельные части, реагировать на :hover. По сути, SVG ведёт себя как статичная PNG картинка, которая просто масштабируемая.

Через CSS background-image аналогично <img>. Удобно для фоновых паттернов и декора, но стилизовать изнутри невозможно.

Inline, прямо в HTML. Вы вставляете код SVG непосредственно в разметку страницы. Это открывает полный доступ к каждому элементу внутри SVG. Можно задавать классы отдельным фигурам, менять их fill и stroke через CSS, анимировать через transition и @keyframes, вешать hover-эффекты. Для веб-плаката это единственный способ, который имеет смысл, когда вам нужна интерактивность.

Как получить SVG-код для inline-вставки? Экспортируйте фигуру из Figma как SVG, откройте файл в текстовом редакторе и вы увидите XML-разметку с тегами <svg>, <path>, <circle>, <rect>. Скопируйте её целиком и вставьте прямо в HTML. Перед вставкой прогоните код через svgomg.net и это уберёт лишние метаданные и сократит размер.

Fill и Stroke

Каждый SVG-элемент имеет два визуальных свойства. fill — это заливка, цвет внутренней области. stroke — это обводка, линия по контуру фигуры. Оба управляются через CSS точно так же, как color или background у обычных HTML элементов.


<svg width="80" height="80" viewBox="0 0 24 24">
  <polygon class="star"
    points="12,2 15,9 22,9 16,14
            18,21 12,17 6,21 8,14 2,9 9,9"/>
</svg>
 
<svg width="80" height="80" viewBox="0 0 24 24">
  <circle class="circle-outline"
    cx="12" cy="12" r="10"/>
</svg>

<svg width="80" height="80" viewBox="0 0 24 24">
  <rect
    class="rect-dual"
    x="3"
    y="3"
    width="18"
    height="18"
    rx="3"
  />
</svg>
      

.star {
  fill: #FE3904;
  stroke: none;
}
 
.circle-outline {
  fill: none;
  stroke: #9EFF70;
  stroke-width: 3;
}
/* fill — заливка, stroke — обводка.
   Это два свойства, которыми вы
   будете управлять чаще всего. */
      

Звёздочка залита красным без обводки. Круг наоборот без заливки, но с зелёной обводкой. Прямоугольник совмещает оба свойства. Этих двух инструментов достаточно для огромного количества визуальных эффектов.

Hover на SVG-элементах

Поскольку inline SVG-элементам можно задавать классы, к ним применяются все те же CSS-псевдоклассы, что и к обычным HTML-элементам. В первую очередь :hover.


<svg width="100" height="100" viewBox="0 0 24 24">
  <circle class="hover-circle"
    cx="12" cy="12" r="10"/>
</svg>
      

.hover-circle {
  fill: #FE3904;
  transition: fill 0.3s ease, transform 0.3s ease;
  cursor: pointer;
}
 
.hover-circle:hover {
  fill: #9EFF70;
  transform: scale(1.15);
}
/* transition делает смену плавной.
   Наведите курсор — круг сменит цвет
   и немного увеличится. */
      

Наведите курсор на каждую фигуру. Круг меняет fill и увеличивается. Прямоугольник получает заливку, которой у него изначально не было. Звёздочка меняет цвет и поворачивается. Всё это — через transition, без JavaScript.

hover можно вешать как на отдельный SVG-элемент, так и на родительский <svg>, чтобы при наведении на всю иконку менялись её внутренние части. Второй подход удобнее, когда нужно координировать несколько изменений одновременно.


<svg class="icon-plus" viewBox="0 0 24 24">
  <circle class="bg" cx="12" cy="12" r="11"/>
  <path class="cross"
    d="M12,6 L12,18 M6,12 L18,12"
    fill="none"/>
</svg>
      

.icon-plus .cross {
  stroke: white;
  stroke-width: 2;
  transition: transform 0.3s ease;
  transform-origin: 12px 12px;
}
 
.icon-plus:hover .cross {
  transform: rotate(90deg);
}
/* transform-origin: 12px 12px — центр
   SVG-холста (viewBox 0 0 24 24).
   Без этого вращение будет
   вокруг левого верхнего угла. */
      

Здесь hover стоит на родительском <svg>. При наведении фон круга меняет цвет, а крестик path поворачивается на 90 градусов, превращаясь из плюса в крестик закрытия. Обратите внимание на transform-origin: 12px 12px — это центр SVG-холста при viewBox 0 0 24 24. Без явного указания transform-origin SVG-элементы вращаются вокруг левого верхнего угла холста, а не вокруг своего центра. Это самая частая ошибка при анимации SVG.

transform-origin в SVG работает иначе, чем в HTML. У HTML элементов по умолчанию точка вращения является центром элемента. У SVG элементов — верхний левый угол SVG-холста 0, 0. Чтобы вращать фигуру вокруг её собственного центра, нужно задать transform-origin явно. Для холста viewBox="0 0 24 24" центр — это 12px 12px, для viewBox="0 0 100 100"50px 50px.

Анимации с SVG

hover-эффекты срабатывают при наведении. Если нужна анимация, которая работает постоянно — пульсация, вращение, подпрыгивание — используйте @keyframes, точно так же, как для обычных HTML элементов.


<svg viewBox="0 0 24 24">
  <circle class="pulse-circle" cx="12" cy="12" r="10"/>
</svg>
      

.pulse-circle {
  fill: #FE3904;
  animation: pulse 2s ease-in-out infinite;
  transform-origin: center;
}
 
@keyframes pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.2); opacity: 0.6; }
}
/* transform-origin: center — обязательно.
   Без него SVG-элемент масштабируется
   от верхнего левого угла холста. */
      

Три фигуры, три разных анимации. Круг пульсирует через scale и opacity. Прямоугольник вращается через rotate 360deg. Звёздочка подпрыгивает через translateY. Все три используют transform-origin: center для корректного поведения и infinite для бесконечного цикла.

Для веб-плаката такие анимации полезны для декоративных SVG элементов. Мерцающие звёзды, вращающиеся шестерёнки, пульсирующие точки — всё это создаёт визуальную среду, не требуя взаимодействия со стороны зрителя.

Эффект рисующейся линии

Это, пожалуй, самый эффектный CSS-трюк, доступный только с SVG. Линия как будто рисуется на экране, постепенно проявляясь от начала к концу. Технически за ним стоят два свойства: stroke-dasharray и stroke-dashoffset.

stroke-dasharray превращает сплошную обводку в пунктир и задаёт длину штриха и промежутка. Если задать длину штриха равной длине всего пути, получится один штрих во всю линию и визуально линия выглядит сплошной. stroke-dashoffset сдвигает этот штрих вдоль пути. Если сдвинуть его на всю длину, штрих уедет за пределы видимой области и линия пропадёт. Анимация возвращает offset к нулю, и штрих постепенно въезжает обратно, создавая эффект рисования.

Атрибут pathLength="100" на SVG-элементе упрощает расчёт. Он говорит браузеру: «Считай, что длина этого пути составляет 100 единиц, независимо от реальной длины». После этого stroke-dasharray: 100 и stroke-dashoffset: 100 всегда будут правильными значениями, без необходимости вычислять длину пути через JavaScript.


<svg viewBox="0 0 100 100">
  <path class="draw-path"
    d="M10,50 Q50,10 90,50 Q50,90 10,50"
    pathLength="100"/>
</svg>
<!-- pathLength="100" упрощает расчёт:
     длина пути всегда 100 единиц -->
      

.draw-path {
  fill: none;
  stroke: #9EFF70;
  stroke-width: 2;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: draw 3s ease forwards
             infinite alternate;
}
 
@keyframes draw {
  to { stroke-dashoffset: 0; }
}
/* stroke-dasharray: 100 — штрих длиной
   во всю линию.
   stroke-dashoffset: 100 — сдвигаем штрих
   так, что линия невидима.
   Анимация возвращает offset к 0 —
   линия рисуется. */
      

Фигура в виде знака бесконечности рисуется и стирается в бесконечном цикле. Три CSS-свойства и один @keyframes.

Тот же эффект можно привязать к hover через transition вместо animation.

Наведи курсор в центр


<svg viewBox="0 0 120 60">
  <path class="draw-hover-path"
    d="M10,50 L30,10 L50,40
       L70,15 L90,45 L110,10"
    pathLength="100"/>
</svg>
      

.draw-hover-path {
  fill: none;
  stroke: #FE3904;
  stroke-width: 2;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 1.5s ease;
}
 
svg:hover .draw-hover-path {
  stroke-dashoffset: 0;
}
/* Тот же принцип, но через transition
   вместо animation. Линия рисуется
   при наведении и стирается
   когда курсор уходит. */
      

Наведите курсор — зигзагообразная линия нарисуется. Уберите курсор — сотрётся обратно. transition на stroke-dashoffset создаёт плавный переход, а длительность 1.5 секунды даёт время насладиться эффектом.

Комбинация приёмов

Самые интересные результаты получаются, когда вы совмещаете несколько SVG-анимаций в одном элементе. Смена fill, рисующаяся обводка и масштабирование могут работать одновременно.


<svg viewBox="0 0 100 100">
  <circle class="combo-bg" cx="50" cy="50" r="48"/>
  <circle class="combo-ring" cx="50" cy="50" r="45"/>
  <polygon class="combo-icon"
    points="40,30 40,70 72,50"/>
</svg>
      

.combo-ring {
  fill: none;
  stroke: #FE3904;
  stroke-width: 2;
  stroke-dasharray: 283;
  stroke-dashoffset: 283;
  transition: stroke-dashoffset 0.8s ease;
}
 
svg:hover .combo-ring {
  stroke-dashoffset: 0;
  stroke: #9EFF70;
}
 
svg:hover .combo-icon {
  fill: white;
  transform: scale(1.1);
}
/* При наведении: кольцо рисуется,
   иконка увеличивается, цвета меняются.
   Три перехода работают одновременно. */
      

Наведите курсор на кнопку воспроизведения. Три вещи происходят одновременно: кольцо «рисуется» по кругу и меняет цвет с красного на зелёный, треугольник-иконка увеличивается и белеет, фон затемняется. Каждый элемент имеет свой transition, и все они срабатывают от одного :hover на родительском <svg>.

Чего SVG не может

SVG не подходит для фотографий. Растровые изображения, фото, скриншоты, сканы, то это точно JPEG, WebP или AVIF. SVG хорош только для графики, которую можно описать кривыми и геометрическими формами.

Сложные SVG из Figma могут быть тяжёлыми. Если иллюстрация содержит сотни path элементов с тысячами точек, SVG-файл может оказаться тяжелее PNG. Прогоняйте такие файлы через svgomg.net и сравнивайте размеры.

Анимация сложных path данных требует JavaScript. CSS позволяет анимировать fill, stroke transform и stroke-dashoffset. Если вам нужно морфить одну форму в другую — менять сам путь d="..." — потребуется JavaScript-библиотека вроде GSAP с плагином MorphSVG.

Хорошее правило: если фигуру можно нарисовать в Illustrator или Figma с помощью Pen Tool, то она подходит для SVG. Если её можно получить только фотографией или сложным растровым рендером, то используйте WebP или AVIF.

Понравилась статья?

Забыли главное или есть что предложить?
Напишите нам в телеграм

Читайте также