SVG Animations Skill — Kanvas Site
SkillWeb & browsingExpert knowledge for SVG animations: GSAP tweening of SVG elements, CSS stroke-dasharray path drawing, and Hugo partial SVG patterns. No React, no Framer Motion, no paid GSAP plugins. GSAP is loaded via CDN (no imports).
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the SVG Animations Skill — Kanvas Site skill
About this capability
Website for Kanvas extension
What this skill tells your AI
The instructions your AI receives, as published by meshery-extensions/kanvas-site in .agents/skills/kanvas-animations/skills/svg-animations/SKILL.md and read by ahel’s review.
Expert knowledge for SVG animations: GSAP tweening of SVG elements, CSS stroke-dasharray
path drawing, and Hugo partial SVG patterns. No React, no Framer Motion, no paid GSAP plugins.
GSAP is loaded via CDN (no imports).
SVG in Hugo Partials
Inline SVGs in Hugo templates are preferred for animatable icons — they can be targeted by CSS and GSAP directly.
<!-- layouts/partials/icon-arrow.html -->
<svg class="icon-arrow" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path class="arrow-shaft"
d="M5 12h14"
stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<path class="arrow-head"
d="M13 6l6 6-6 6"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round"/>
</svg>
// _base.scss — arrow hover
.btn:hover .arrow-shaft { transform: scaleX(1.2); transform-origin: left; }
.btn:hover .arrow-head { transform: translateX(3px); }
CSS stroke-dasharray Path Drawing
No JS needed for simple draw-on-scroll — use CSS transitions triggered by JS class:
.path-draw {
stroke-dasharray: 500;
stroke-dashoffset: 500;
transition: stroke-dashoffset 1.2s cubic-bezier(0.16, 1, 0.3, 1);
&.is-drawn {
stroke-dashoffset: 0;
}
}
// Trigger draw via IntersectionObserver or ScrollTrigger
ScrollTrigger.create({
trigger: '.path-svg',
start: 'top 80%',
once: true,
onEnter: (self) => {
const paths = self && self.trigger
? self.trigger.querySelectorAll('.path-draw')
: null;
if (!paths || paths.length === 0) return;
paths.forEach((path) => path.classList.add('is-drawn'));
},
});
Getting path length
// In the browser console or a one-time script:
const path = document.querySelector('.my-path');
console.log(path.getTotalLength()); // use this value for stroke-dasharray
GSAP SVG Tweening
GSAP can animate any SVG attribute or CSS property on SVG elements:
// Opacity and transform (most common)
gsap.from('.svg-icon', { opacity: 0, scale: 0.8, duration: 0.5, ease: 'back.out(1.4)' });
// stroke-dashoffset (path drawing with scrub)
const path = document.querySelector('.circuit-path');
const pathLen = path.getTotalLength();
gsap.set(path, { strokeDasharray: pathLen, strokeDashoffset: pathLen });
gsap.to(path, {
strokeDashoffset: 0,
scrollTrigger: { trigger: '.circuit-section', start: 'top 80%', end: 'top 30%', scrub: 1 }
});
// SVG fill-opacity
gsap.from('.icon-fill', { fillOpacity: 0, duration: 0.4 });
// Rotate SVG around its center
gsap.to('.spinner-svg', { rotation: 360, duration: 2, repeat: -1, ease: 'none',
transformOrigin: '50% 50%' });
Scrub-Linked SVG Entrance (project pattern)
// section SVG icons entering on scroll
scrubEach(
document.querySelectorAll('.feature-icon svg'),
{ opacity: 0, scale: 0.7, y: 20 },
'.features-section',
88, 55, 4
);
GSAP SVG Nav Icon Animation
From main.js — nav anchors with SVG icons brighten on hover/active:
document.querySelectorAll('.main-nav a').forEach(anchor => {
anchor.addEventListener('mouseenter', () => {
const svg = anchor.querySelector('svg');
if (svg) gsap.to(svg, { opacity: 0.85, duration: 0.6, overwrite: true });
});
anchor.addEventListener('mouseleave', () => {
const svg = anchor.querySelector('svg');
if (svg) gsap.set(svg, { opacity: 1 });
});
});
CSS @keyframes SVG Effects
// Spinning loader ring
.spinner-ring {
stroke-dasharray: 126; // ~2 * PI * 20
stroke-dashoffset: 126;
animation: spinDraw 1.4s ease-in-out infinite;
transform-origin: center;
}
@keyframes spinDraw {
0% { stroke-dashoffset: 126; transform: rotate(0deg); }
50% { stroke-dashoffset: 32; }
100% { stroke-dashoffset: 126; transform: rotate(360deg); }
}
// Pulsing icon fill
@keyframes iconPulse {
0%, 100% { fill-opacity: 0.7; transform: scale(1); }
50% { fill-opacity: 1; transform: scale(1.05); }
}
.icon-pulse {
animation: iconPulse 2.5s ease-in-out infinite;
transform-origin: center;
}
SVG SCSS Conventions
// SVG inherits text color via currentColor — use this pattern
.icon {
width: 1.25em;
height: 1.25em;
stroke: currentColor; // or fill: currentColor
stroke-width: 2;
overflow: visible;
flex-shrink: 0;
}
// Hover transition on SVG path
.nav-icon {
transition: stroke 0.2s ease, opacity 0.2s ease;
&:hover {
stroke: $primary;
}
}
Scroll Cube SVG
The hero scroll cube uses inline SVGs injected by main.js. Each face is a <svg> with a
<path> clipping mask. GSAP animates rotateY, x, y, opacity on each piece element
(not the SVG attributes themselves).
// main.js pattern
const piece = document.createElement('div');
piece.className = 'scroll-cube-piece';
piece.innerHTML = '<svg viewBox="130 30 440 490" xmlns="http://www.w3.org/2000/svg">' +
'<path d="..." fill="rgba(0,179,159,0.15)" .../>' + '</svg>';
wrapper.appendChild(piece);
// GSAP animates the wrapper div, not the SVG internals
gsap.set(piece, { rotateY: Math.random() * 180 - 90, x: (Math.random() - 0.5) * 200, opacity: 0 });
Anti-Patterns
MorphSVGPlugin— paid GSAP plugin, not available on CDN- Animating
dattribute directly in GSAP — not supported without MorphSVG - React
<motion.path>or<motion.circle>— no React in this project - Inline
style="..."on SVG elements — use SCSS classes getTotalLength()in production code — calculate once offline, hardcode the value
Signals
- GitHub stars
- 39
- Forks
- 49
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
svg-animations-meshery-extensions- Source
- github.com/meshery-extensions/kanvas-site