Практическое руководство: Анимация SVG с помощью <use> и CSS-переменных

Практическое руководство: Анимация SVG с помощью <use> и CSS-переменных

Элементы <symbol> и <use> в SVG позволяют создавать переиспользуемые графические элементы. Однако их анимация может быть сложной из-за ограничений Shadow DOM. В этом руководстве вы узнаете, как использовать CSS-переменные для анимации элементов внутри <symbol>.

Основная проблема: Barrier Shadow DOM

Когда вы ссылаетесь на содержимое <symbol> через <use>, браузер создает его копию в Shadow DOM. Это означает, что внешние CSS-стили не могут напрямую воздействовать на элементы внутри символа.

НЕ РАБОТАЕТ:

<symbol id="outlaw-1">
  <g class="outlaw-1-foot">...</g>
</symbol>

<use href="#outlaw-1" class="tapping" />
.tapping {
  animation: tapping 1s ease-in-out infinite; /* Не сработает! */
}

Решение: CSS-переменные

Обычные CSS-значения не могут преодолеть границу Shadow DOM, но CSS-переменные могут. Это ключ к анимации элементов внутри <symbol>.

Шаг 1: Подготовка символа

Добавьте CSS-переменные через inline-стили в элементы внутри символа:

<symbol id="outlaw-1">
  <g class="outlaw-1-foot" style="
    transform-origin: bottom right; 
    transform-box: fill-box; 
    transform: rotate(var(--foot-rotate, 0deg));">
    <!-- ... -->
  </g>
</symbol>
Несколько анимированных элементов внутри одного SVG-символаНесколько анимированных элементов внутри одного SVG-символа

Шаг 2: Создание анимации

Определите ключевые кадры, изменяющие CSS-переменные:

@keyframes tapping {
  0%, 60%, 100% { --foot-rotate: 0deg; }
  20% { --foot-rotate: -5deg; }
  40% { --foot-rotate: 2deg; }
}

Шаг 3: Применение анимации

Примените анимацию к элементам <use>:

use[data-outlaw="1"] {
  --foot-rotate: 0deg;
  animation: tapping 1s ease-in-out infinite;
}

Практические примеры

Пример 1: Многоцветная система иконок

Создайте переиспользуемые иконки с настраиваемыми цветами:

<symbol id="icon-bluesky">
  <path fill="var(--icon-fill, currentColor)" d="..." />
</symbol>

Использование с разными цветами:

<header>
  <svg xmlns="http://www.w3.org/2000/svg">
    <use href="#icon-bluesky" style="--icon-fill: #2d373b;" />
  </svg>
</header>

<footer>
  <svg xmlns="http://www.w3.org/2000/svg">
    <use href="#icon-bluesky" style="--icon-fill: #590d1a;" />
  </svg>
</footer>
Кастомные свойства для цветов заливки в нескольких иконках BlueskyКастомные свойства для цветов заливки в нескольких иконках Bluesky

Пример 2: Визуализация данных

Создайте инфографику с переиспользуемыми элементами:

<symbol id="career-bar">
  <rect
    height="10"
    width="var(--career-length, 100)" 
    fill="var(--career-colour, #f7bea1)"
  />
</symbol>

Использование для разных наборов данных:

<use href="#career-bar" style="--career-length: 400; --career-color: #769099;"/>
<use href="#career-bar" style="--career-length: 300; --career-color: #f7bea1;"/>
<use href="#career-bar" style="--career-length: 200; --career-color: #c2d1d6;"/>
Пример инфографики с настраиваемыми барами разных размеров и цветовПример инфографики с настраиваемыми барами разных размеров и цветов

Пример 3: Сложные анимации персонажей

Создайте живых персонажей с множеством анимаций:

Моргание глаз:

<symbol id="outlaw-1">
  <g class="eyelids" style="opacity: var(--eyelids-opacity, 1);">
    <!-- ... -->
  </g>
</symbol>
@keyframes blink {
  0%, 92% { --eyelids-opacity: 0; }
  93%, 94% { --eyelids-opacity: 1; }
  95%, 97% { --eyelids-opacity: 0.1; }
  98%, 100% { --eyelids-opacity: 0; }
}

Постукивание ногой:

<g class="outlaw-1-foot" style="
  transform-origin: bottom right; 
  transform: rotate(var(--foot-rotate));">
</g>
@keyframes tapping {
  0%, 60%, 100% { --foot-rotate: 0deg; }
  20% { --foot-rotate: -5deg; }
  40% { --foot-rotate: 2deg; }
}

Дрожание усов:

<g class="outlaw-1-tashe" style="
  transform: translateX(var(--jiggle-x, 0px));">
  <!-- ... -->
</g>
@keyframes jiggle {
  0%, 100% { --jiggle-x: 0px; }
  20% { --jiggle-x: -3px; }
  40% { --jiggle-x: 2px; }
  60% { --jiggle-x: -1px; }
  80% { --jiggle-x: 4px; }
}
Эффект моргания через анимацию прозрачности векЭффект моргания через анимацию прозрачности векЭффект постукивания через анимацию вращения ногиЭффект постукивания через анимацию вращения ногиЭффект дрожания через анимацию перемещения усовЭффект дрожания через анимацию перемещения усов

Комбинирование анимаций

Объедините несколько анимаций для сложных эффектов:

use[data-outlaw] {
  --blink-duration: 4s;
  --eyelids-opacity: 1;
  --foot-rotate: 0deg;
  --jiggle-x: 0px;
  animation: 
    blink var(--blink-duration) infinite var(--blink-delay),
    jiggle 1s ease-in-out infinite,
    tapping 1s ease-in-out infinite;
}

/* Разные задержки для каждого персонажа */
use[data-outlaw="1"] { --blink-delay: 1s; }
use[data-outlaw="2"] { --blink-delay: 2s; }
use[data-outlaw="3"] { --blink-delay: 3s; }

Важные рекомендации

  1. Всегда используйте fallback-значения: opacity: var(--eyelids-opacity, 1);
  2. CSS-переменные работают только с var(): Элементы должны явно ссылаться на переменные через var().
  3. Проверяйте значения в DevTools: Используйте панель Computed Styles для отладки CSS-переменных.
  4. Inline-стили имеют приоритет: Помните о каскаде при комбинировании разных подходов.

Заключение

CSS-переменные служат мостом через барьер Shadow DOM, позволяя создавать сложные анимации для переиспользуемых SVG-символов. Этот подход делает код:

  • Чище — меньше дублирования
  • Легче — меньший размер файлов
  • Гибче — легкая настройка анимаций

Начните с простых анимаций и постепенно переходите к более сложным композициям, используя силу CSS-переменных для оживления ваших SVG-графиков.

2026