Практическое руководство: Анимация 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-символа
Шаг 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
Пример 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; }Важные рекомендации
- Всегда используйте fallback-значения:
opacity: var(--eyelids-opacity, 1); - CSS-переменные работают только с
var():
Элементы должны явно ссылаться на переменные черезvar(). - Проверяйте значения в DevTools:
Используйте панель Computed Styles для отладки CSS-переменных. - Inline-стили имеют приоритет:
Помните о каскаде при комбинировании разных подходов.
Заключение
CSS-переменные служат мостом через барьер Shadow DOM, позволяя создавать сложные анимации для переиспользуемых SVG-символов. Этот подход делает код:
- Чище — меньше дублирования
- Легче — меньший размер файлов
- Гибче — легкая настройка анимаций
Начните с простых анимаций и постепенно переходите к более сложным композициям, используя силу CSS-переменных для оживления ваших SVG-графиков.