moai-tool-svg
SVG creation, optimization, and transformation specialist. Use when creating vector graphics, optimizing SVG files with SVGO, implementing icon systems, building data visualizations, or adding SVG animations.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install modu-ai-moai-adk-moai-tool-svg
Repository
Skill path: .claude/skills/moai-tool-svg
SVG creation, optimization, and transformation specialist. Use when creating vector graphics, optimizing SVG files with SVGO, implementing icon systems, building data visualizations, or adding SVG animations.
Open repositoryBest for
Primary workflow: Analyze Data & AI.
Technical facets: Full Stack, Data / AI.
Target audience: everyone.
License: Apache-2.0.
Original source
Catalog source: SkillHub Club.
Repository owner: modu-ai.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install moai-tool-svg into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/modu-ai/moai-adk before adding moai-tool-svg to shared team environments
- Use moai-tool-svg for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: moai-tool-svg
description: >
SVG creation, optimization, and transformation specialist. Use when creating vector
graphics, optimizing SVG files with SVGO, implementing icon systems, building data
visualizations, or adding SVG animations.
license: Apache-2.0
compatibility: Designed for Claude Code
allowed-tools: Read Grep Glob Bash(svgo:*) Bash(npx:*) WebFetch
user-invocable: false
metadata:
version: "1.0.0"
category: "tool"
modularized: "true"
status: "active"
updated: "2026-01-26"
tags: "svg, vector, graphics, svgo, optimization, animation, icons"
related-skills: "moai-domain-frontend, moai-docs-generation"
context7-libraries: "/nicolo-ribaudo/svgo"
---
# SVG Creation and Optimization Specialist
Comprehensive SVG development covering vector graphics creation, SVGO optimization, icon systems, data visualizations, and animations. This skill provides patterns for all SVG workflows from basic shapes to complex animated graphics.
---
## Quick Reference (30 seconds)
### Basic SVG Template
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<title>Accessible Title</title>
<desc>Description for screen readers</desc>
<!-- Content here -->
</svg>
```
### Common Shapes Cheatsheet
Rectangle: `<rect x="10" y="10" width="80" height="60" rx="5" />`
Circle: `<circle cx="50" cy="50" r="40" />`
Ellipse: `<ellipse cx="50" cy="50" rx="40" ry="25" />`
Line: `<line x1="10" y1="10" x2="90" y2="90" stroke="black" />`
Polyline: `<polyline points="10,10 50,50 90,10" fill="none" stroke="black" />`
Polygon: `<polygon points="50,10 90,90 10,90" />`
### Path Commands Quick Reference
Movement Commands:
- M x y: Move to absolute position
- m dx dy: Move relative
- L x y: Line to absolute
- l dx dy: Line relative
- H x: Horizontal line absolute
- h dx: Horizontal line relative
- V y: Vertical line absolute
- v dy: Vertical line relative
- Z: Close path
Curve Commands:
- C x1 y1 x2 y2 x y: Cubic bezier (two control points)
- S x2 y2 x y: Smooth cubic (reflects previous control)
- Q x1 y1 x y: Quadratic bezier (one control point)
- T x y: Smooth quadratic (reflects previous control)
- A rx ry rotation large-arc sweep x y: Arc
### SVGO CLI Commands
Install globally: `npm install -g svgo`
Optimize single file: `svgo input.svg -o output.svg`
Optimize directory: `svgo -f ./src/icons -o ./dist/icons`
Show optimization stats: `svgo input.svg --pretty --indent=2`
Use config file: `svgo input.svg --config svgo.config.mjs`
### Fill and Stroke Quick Reference
Fill properties: fill, fill-opacity, fill-rule (nonzero, evenodd)
Stroke properties: stroke, stroke-width, stroke-opacity, stroke-linecap (butt, round, square), stroke-linejoin (miter, round, bevel), stroke-dasharray, stroke-dashoffset
---
## Implementation Guide (5 minutes)
### SVG Document Structure
The SVG element requires the xmlns attribute for standalone files. The viewBox defines the coordinate system as "minX minY width height". Width and height set the rendered size.
```xml
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 200 200"
width="200" height="200"
preserveAspectRatio="xMidYMid meet">
<!-- Reusable definitions -->
<defs>
<linearGradient id="grad1">
<stop offset="0%" stop-color="#ff0000" />
<stop offset="100%" stop-color="#0000ff" />
</linearGradient>
</defs>
<!-- Grouped content -->
<g id="main-group" transform="translate(10, 10)">
<rect width="100" height="100" fill="url(#grad1)" />
</g>
</svg>
```
### Creating Reusable Symbols
Symbols define reusable graphics that can be instantiated with use elements. They support their own viewBox for scaling.
```xml
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="icon-star" viewBox="0 0 24 24">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</symbol>
</defs>
<!-- Use the symbol multiple times -->
<use href="#icon-star" x="0" y="0" width="24" height="24" />
<use href="#icon-star" x="30" y="0" width="24" height="24" fill="gold" />
<use href="#icon-star" x="60" y="0" width="48" height="48" />
</svg>
```
### Path Creation Patterns
Simple icon path combining moves, lines, and curves:
```xml
<path d="M10 20 L20 10 L30 20 L20 30 Z" />
```
Rounded rectangle using arcs:
```xml
<path d="M15 5 H85 A10 10 0 0 1 95 15 V85 A10 10 0 0 1 85 95 H15 A10 10 0 0 1 5 85 V15 A10 10 0 0 1 15 5 Z" />
```
Heart shape using cubic beziers:
```xml
<path d="M50 88 C20 65 5 45 5 30 A15 15 0 0 1 35 30 Q50 45 50 45 Q50 45 65 30 A15 15 0 0 1 95 30 C95 45 80 65 50 88 Z" />
```
### Gradient Implementation
Linear gradient from left to right:
```xml
<defs>
<linearGradient id="horizontal-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#3498db" />
<stop offset="50%" stop-color="#9b59b6" />
<stop offset="100%" stop-color="#e74c3c" />
</linearGradient>
</defs>
<rect fill="url(#horizontal-grad)" width="200" height="100" />
```
Radial gradient with focal point:
```xml
<defs>
<radialGradient id="sphere-grad" cx="50%" cy="50%" r="50%" fx="30%" fy="30%">
<stop offset="0%" stop-color="#ffffff" />
<stop offset="100%" stop-color="#3498db" />
</radialGradient>
</defs>
<circle fill="url(#sphere-grad)" cx="50" cy="50" r="40" />
```
### SVGO Configuration
Create svgo.config.mjs in project root:
```javascript
export default {
multipass: true,
plugins: [
'preset-default',
'prefixIds',
{
name: 'sortAttrs',
params: {
xmlnsOrder: 'alphabetical'
}
},
{
name: 'removeAttrs',
params: {
attrs: ['data-name', 'class']
}
}
]
};
```
Configuration preserving specific elements:
```javascript
export default {
multipass: true,
plugins: [
{
name: 'preset-default',
params: {
overrides: {
removeViewBox: false,
cleanupIds: {
preserve: ['icon-', 'logo-']
}
}
}
}
]
};
```
### Embedding SVG in React
Inline SVG component:
```tsx
const Icon = ({ size = 24, color = 'currentColor' }) => (
<svg width={size} height={size} viewBox="0 0 24 24" fill="none">
<path d="M12 2L2 7l10 5 10-5-10-5z" stroke={color} strokeWidth="2" />
</svg>
);
```
SVG sprite with use element:
```tsx
const SpriteIcon = ({ name, size = 24 }) => (
<svg width={size} height={size}>
<use href={`/sprites.svg#${name}`} />
</svg>
);
```
### Text Elements
Basic text positioning:
```xml
<text x="50" y="50" text-anchor="middle" dominant-baseline="middle"
font-family="Arial" font-size="16" fill="#333">
Centered Text
</text>
```
Text on a path:
```xml
<defs>
<path id="text-curve" d="M10 80 Q95 10 180 80" fill="none" />
</defs>
<text font-size="14">
<textPath href="#text-curve">Text following a curved path</textPath>
</text>
```
---
## Advanced Implementation (10+ minutes)
### Complex Filter Effects
Drop shadow with blur:
```xml
<defs>
<filter id="drop-shadow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur" />
<feOffset in="blur" dx="3" dy="3" result="offsetBlur" />
<feMerge>
<feMergeNode in="offsetBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
```
Glow effect:
```xml
<filter id="glow">
<feGaussianBlur stdDeviation="4" result="coloredBlur" />
<feMerge>
<feMergeNode in="coloredBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
```
### Clipping and Masking
Clip path for cropping:
```xml
<defs>
<clipPath id="circle-clip">
<circle cx="50" cy="50" r="40" />
</clipPath>
</defs>
<image href="photo.jpg" width="100" height="100" clip-path="url(#circle-clip)" />
```
Gradient mask for fade effect:
```xml
<defs>
<linearGradient id="fade-grad">
<stop offset="0%" stop-color="white" />
<stop offset="100%" stop-color="black" />
</linearGradient>
<mask id="fade-mask">
<rect width="100" height="100" fill="url(#fade-grad)" />
</mask>
</defs>
<rect width="100" height="100" fill="blue" mask="url(#fade-mask)" />
```
### CSS Animation Integration
Keyframe animation for SVG elements:
```css
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.8; }
}
.animated-circle {
animation: pulse 2s ease-in-out infinite;
transform-origin: center;
}
```
Stroke drawing animation:
```css
.draw-path {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw 2s ease forwards;
}
@keyframes draw {
to { stroke-dashoffset: 0; }
}
```
### Accessibility Best Practices
Always include title and desc for meaningful graphics:
```xml
<svg role="img" aria-labelledby="title desc">
<title id="title">Company Logo</title>
<desc id="desc">A blue mountain with snow-capped peak</desc>
<!-- graphic content -->
</svg>
```
For decorative SVGs, hide from screen readers:
```xml
<svg aria-hidden="true" focusable="false">
<!-- decorative content -->
</svg>
```
### Performance Optimization
Reduce precision in path data from 6 decimals to 2:
Before: `M10.123456 20.654321 L30.987654 40.123456`
After: `M10.12 20.65 L30.99 40.12`
Convert shapes to paths for smaller file size when appropriate. Use symbols for repeated elements. Apply SVGZ compression for 20-50% size reduction.
For detailed patterns on each topic, see the modules directory.
---
## Module Index
- modules/svg-basics.md: Document structure, coordinate system, shapes, paths, text
- modules/svg-styling.md: Fills, strokes, gradients, patterns, filters, clipping, masking
- modules/svg-optimization.md: SVGO configuration, compression, sprites, performance
- modules/svg-animation.md: CSS animations, SMIL, JavaScript, interaction patterns
---
## Works Well With
- moai-domain-frontend: React/Vue SVG component integration
- moai-docs-generation: SVG diagram generation for documentation
- moai-domain-uiux: Icon systems and design system integration
---
## Skill Companion Files
> Additional files collected from the skill directory layout.
### references/examples.md
```markdown
# SVG Working Examples
Complete, working code examples for common SVG patterns and use cases.
---
## Example 1: Responsive Icon System
Icon component with size and color props:
```xml
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<defs>
<symbol id="icon-home" viewBox="0 0 24 24">
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol id="icon-settings" viewBox="0 0 24 24">
<path d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
fill="none" stroke="currentColor" stroke-width="2"/>
<circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-width="2"/>
</symbol>
<symbol id="icon-user" viewBox="0 0 24 24">
<path d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
</defs>
</svg>
<!-- Usage -->
<svg class="icon icon-small"><use href="#icon-home"/></svg>
<svg class="icon icon-medium" style="color: blue;"><use href="#icon-settings"/></svg>
<svg class="icon icon-large" style="color: green;"><use href="#icon-user"/></svg>
```
CSS for icon sizing:
```css
.icon { display: inline-block; }
.icon-small { width: 16px; height: 16px; }
.icon-medium { width: 24px; height: 24px; }
.icon-large { width: 32px; height: 32px; }
```
---
## Example 2: Logo with Gradients
Company logo with multiple gradients:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 60" width="200" height="60">
<defs>
<linearGradient id="logo-grad-1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#667eea"/>
<stop offset="100%" stop-color="#764ba2"/>
</linearGradient>
<linearGradient id="logo-grad-2" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#f093fb"/>
<stop offset="100%" stop-color="#f5576c"/>
</linearGradient>
</defs>
<g transform="translate(10, 10)">
<!-- Logo mark -->
<circle cx="20" cy="20" r="18" fill="url(#logo-grad-1)"/>
<path d="M12 20 L20 12 L28 20 L20 28 Z" fill="white"/>
<!-- Logo text -->
<text x="50" y="28" font-family="Arial, sans-serif" font-size="24" font-weight="bold" fill="url(#logo-grad-2)">
BrandName
</text>
</g>
</svg>
```
---
## Example 3: Animated Loading Spinner
CSS-animated spinner:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50" height="50">
<style>
.spinner-track { fill: none; stroke: #e0e0e0; stroke-width: 4; }
.spinner-head {
fill: none;
stroke: #3498db;
stroke-width: 4;
stroke-linecap: round;
stroke-dasharray: 80, 200;
stroke-dashoffset: 0;
animation: spinner-dash 1.5s ease-in-out infinite;
transform-origin: center;
}
@keyframes spinner-dash {
0% { stroke-dasharray: 1, 200; stroke-dashoffset: 0; }
50% { stroke-dasharray: 89, 200; stroke-dashoffset: -35; }
100% { stroke-dasharray: 89, 200; stroke-dashoffset: -124; }
}
.spinner-container { animation: spinner-rotate 2s linear infinite; transform-origin: center; }
@keyframes spinner-rotate { 100% { transform: rotate(360deg); } }
</style>
<circle class="spinner-track" cx="25" cy="25" r="20"/>
<g class="spinner-container">
<circle class="spinner-head" cx="25" cy="25" r="20"/>
</g>
</svg>
```
---
## Example 4: Data Visualization Bar Chart
Interactive bar chart with hover effects:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 250" width="400" height="250">
<style>
.bar { transition: fill 0.3s; cursor: pointer; }
.bar:hover { fill: #e74c3c; }
.axis { stroke: #333; stroke-width: 1; }
.grid { stroke: #e0e0e0; stroke-width: 0.5; }
.label { font-family: Arial, sans-serif; font-size: 12px; fill: #666; }
.value { font-family: Arial, sans-serif; font-size: 10px; fill: #333; text-anchor: middle; }
</style>
<defs>
<linearGradient id="bar-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#3498db"/>
<stop offset="100%" stop-color="#2980b9"/>
</linearGradient>
</defs>
<!-- Grid lines -->
<g class="grid">
<line x1="50" y1="50" x2="380" y2="50"/>
<line x1="50" y1="100" x2="380" y2="100"/>
<line x1="50" y1="150" x2="380" y2="150"/>
</g>
<!-- Axes -->
<line class="axis" x1="50" y1="200" x2="380" y2="200"/>
<line class="axis" x1="50" y1="50" x2="50" y2="200"/>
<!-- Y-axis labels -->
<text class="label" x="40" y="55" text-anchor="end">100</text>
<text class="label" x="40" y="105" text-anchor="end">75</text>
<text class="label" x="40" y="155" text-anchor="end">50</text>
<text class="label" x="40" y="205" text-anchor="end">0</text>
<!-- Bars -->
<rect class="bar" x="70" y="80" width="50" height="120" fill="url(#bar-grad)" rx="3"/>
<rect class="bar" x="140" y="110" width="50" height="90" fill="url(#bar-grad)" rx="3"/>
<rect class="bar" x="210" y="60" width="50" height="140" fill="url(#bar-grad)" rx="3"/>
<rect class="bar" x="280" y="130" width="50" height="70" fill="url(#bar-grad)" rx="3"/>
<!-- Value labels -->
<text class="value" x="95" y="75">80</text>
<text class="value" x="165" y="105">60</text>
<text class="value" x="235" y="55">93</text>
<text class="value" x="305" y="125">47</text>
<!-- X-axis labels -->
<text class="label" x="95" y="220" text-anchor="middle">Q1</text>
<text class="label" x="165" y="220" text-anchor="middle">Q2</text>
<text class="label" x="235" y="220" text-anchor="middle">Q3</text>
<text class="label" x="305" y="220" text-anchor="middle">Q4</text>
</svg>
```
---
## Example 5: Path Drawing Animation
Line drawing effect for illustration:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
<style>
.draw-line {
fill: none;
stroke: #2c3e50;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 500;
stroke-dashoffset: 500;
animation: draw 2s ease forwards;
}
.draw-line:nth-child(2) { animation-delay: 0.5s; }
.draw-line:nth-child(3) { animation-delay: 1s; }
@keyframes draw {
to { stroke-dashoffset: 0; }
}
</style>
<!-- House outline -->
<path class="draw-line" d="M30 100 L100 40 L170 100"/>
<path class="draw-line" d="M50 100 L50 160 L150 160 L150 100"/>
<path class="draw-line" d="M80 160 L80 120 L120 120 L120 160"/>
</svg>
```
---
## Example 6: Complex Filter Effect
Glass morphism card effect:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200" width="300" height="200">
<defs>
<!-- Background blur filter -->
<filter id="glass-blur" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"/>
<feColorMatrix in="blur" type="matrix"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 0.8 0"/>
</filter>
<!-- Drop shadow -->
<filter id="card-shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="10" stdDeviation="20" flood-color="rgba(0,0,0,0.2)"/>
</filter>
<!-- Gradient overlay -->
<linearGradient id="glass-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="rgba(255,255,255,0.4)"/>
<stop offset="100%" stop-color="rgba(255,255,255,0.1)"/>
</linearGradient>
</defs>
<!-- Background pattern -->
<rect width="300" height="200" fill="#667eea"/>
<circle cx="50" cy="50" r="60" fill="#764ba2" opacity="0.5"/>
<circle cx="250" cy="150" r="80" fill="#f093fb" opacity="0.5"/>
<!-- Glass card -->
<g filter="url(#card-shadow)">
<rect x="50" y="40" width="200" height="120" rx="15" fill="white" opacity="0.2" filter="url(#glass-blur)"/>
<rect x="50" y="40" width="200" height="120" rx="15" fill="url(#glass-gradient)" stroke="rgba(255,255,255,0.3)" stroke-width="1"/>
</g>
<!-- Card content -->
<text x="150" y="90" text-anchor="middle" font-family="Arial" font-size="18" font-weight="bold" fill="white">Glass Card</text>
<text x="150" y="115" text-anchor="middle" font-family="Arial" font-size="12" fill="rgba(255,255,255,0.8)">Frosted glass effect</text>
</svg>
```
---
## Example 7: Responsive Illustration
Illustration that scales with container:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300" preserveAspectRatio="xMidYMid meet" style="width: 100%; max-width: 400px; height: auto;">
<title>Mountain Landscape</title>
<desc>A scenic mountain landscape with sun and trees</desc>
<defs>
<linearGradient id="sky-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#87CEEB"/>
<stop offset="100%" stop-color="#E0F6FF"/>
</linearGradient>
<linearGradient id="mountain-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#5D6D7E"/>
<stop offset="100%" stop-color="#85929E"/>
</linearGradient>
<radialGradient id="sun-grad" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#FFF5CC"/>
<stop offset="100%" stop-color="#FFD700"/>
</radialGradient>
</defs>
<!-- Sky -->
<rect width="400" height="300" fill="url(#sky-grad)"/>
<!-- Sun -->
<circle cx="320" cy="60" r="35" fill="url(#sun-grad)"/>
<!-- Mountains -->
<polygon points="0,300 100,150 200,300" fill="url(#mountain-grad)"/>
<polygon points="150,300 280,120 400,300" fill="#34495E"/>
<polygon points="250,300 350,180 400,250 400,300" fill="#5D6D7E"/>
<!-- Snow caps -->
<polygon points="100,150 120,180 80,180" fill="white"/>
<polygon points="280,120 300,150 260,150" fill="white"/>
<!-- Ground -->
<rect y="250" width="400" height="50" fill="#27AE60"/>
<!-- Trees -->
<g transform="translate(50, 220)">
<polygon points="15,0 0,50 30,50" fill="#1E8449"/>
<rect x="12" y="50" width="6" height="15" fill="#6E2C00"/>
</g>
<g transform="translate(350, 210)">
<polygon points="20,0 0,60 40,60" fill="#1E8449"/>
<rect x="16" y="60" width="8" height="20" fill="#6E2C00"/>
</g>
</svg>
```
---
## Example 8: Interactive Button
Button with hover and click states:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 50" width="160" height="50" style="cursor: pointer;">
<style>
.btn-bg {
fill: #3498db;
transition: fill 0.2s, transform 0.1s;
}
.btn-bg:hover { fill: #2980b9; }
.btn-bg:active { transform: translateY(2px); fill: #1a5276; }
.btn-text {
fill: white;
font-family: Arial, sans-serif;
font-size: 16px;
font-weight: bold;
pointer-events: none;
}
.btn-icon {
fill: white;
pointer-events: none;
}
</style>
<defs>
<filter id="btn-shadow">
<feDropShadow dx="0" dy="3" stdDeviation="3" flood-color="rgba(0,0,0,0.3)"/>
</filter>
</defs>
<rect class="btn-bg" x="5" y="5" width="150" height="40" rx="8" filter="url(#btn-shadow)"/>
<g class="btn-icon" transform="translate(20, 15)">
<path d="M10 0 L20 10 L10 20 L0 10 Z"/>
</g>
<text class="btn-text" x="90" y="30" text-anchor="middle">Click Me</text>
</svg>
```
---
## Example 9: Pie Chart
Data visualization pie chart:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200" width="300" height="200">
<style>
.slice { transition: transform 0.2s; transform-origin: 100px 100px; }
.slice:hover { transform: scale(1.05); }
.legend-text { font-family: Arial, sans-serif; font-size: 12px; }
</style>
<!-- Pie slices using path arcs -->
<!-- 40% slice (144 degrees) -->
<path class="slice" d="M100 100 L100 20 A80 80 0 0 1 176.6 148.3 Z" fill="#3498db"/>
<!-- 30% slice (108 degrees) -->
<path class="slice" d="M100 100 L176.6 148.3 A80 80 0 0 1 38.4 164.7 Z" fill="#e74c3c"/>
<!-- 20% slice (72 degrees) -->
<path class="slice" d="M100 100 L38.4 164.7 A80 80 0 0 1 23.4 51.7 Z" fill="#f39c12"/>
<!-- 10% slice (36 degrees) -->
<path class="slice" d="M100 100 L23.4 51.7 A80 80 0 0 1 100 20 Z" fill="#27ae60"/>
<!-- Legend -->
<g transform="translate(210, 40)">
<rect width="15" height="15" fill="#3498db"/>
<text class="legend-text" x="20" y="12">Product A (40%)</text>
<rect y="25" width="15" height="15" fill="#e74c3c"/>
<text class="legend-text" x="20" y="37">Product B (30%)</text>
<rect y="50" width="15" height="15" fill="#f39c12"/>
<text class="legend-text" x="20" y="62">Product C (20%)</text>
<rect y="75" width="15" height="15" fill="#27ae60"/>
<text class="legend-text" x="20" y="87">Product D (10%)</text>
</g>
</svg>
```
---
## Example 10: SMIL Animation
Native SVG animation without CSS:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200">
<!-- Bouncing ball -->
<circle cx="100" cy="50" r="20" fill="#e74c3c">
<animate attributeName="cy" values="50;150;50" dur="1s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1; 0.5 0 0.5 1"/>
<animate attributeName="rx" values="20;22;20" dur="1s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1; 0.5 0 0.5 1"/>
</circle>
<!-- Shadow -->
<ellipse cx="100" cy="170" rx="20" ry="5" fill="rgba(0,0,0,0.3)">
<animate attributeName="rx" values="20;30;20" dur="1s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1; 0.5 0 0.5 1"/>
<animate attributeName="opacity" values="0.3;0.1;0.3" dur="1s" repeatCount="indefinite" calcMode="spline" keySplines="0.5 0 0.5 1; 0.5 0 0.5 1"/>
</ellipse>
<!-- Rotating star -->
<g transform="translate(100, 100)">
<polygon points="0,-30 7,-10 30,-10 12,5 18,30 0,15 -18,30 -12,5 -30,-10 -7,-10" fill="#f39c12">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="4s" repeatCount="indefinite"/>
</polygon>
</g>
<!-- Pulsing circle -->
<circle cx="50" cy="50" r="10" fill="#3498db" opacity="0.7">
<animate attributeName="r" values="10;15;10" dur="1.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.7;0.3;0.7" dur="1.5s" repeatCount="indefinite"/>
</circle>
</svg>
```
---
## Example 11: Text Path Animation
Animated text along curved path:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 150" width="300" height="150">
<defs>
<path id="wave-path" d="M0 75 Q75 25 150 75 T300 75" fill="none"/>
</defs>
<style>
.wave-text {
font-family: Arial, sans-serif;
font-size: 14px;
fill: #3498db;
}
</style>
<!-- Visible path for reference -->
<use href="#wave-path" stroke="#e0e0e0" stroke-width="1"/>
<!-- Animated text -->
<text class="wave-text">
<textPath href="#wave-path">
This text follows a wavy path and animates smoothly
<animate attributeName="startOffset" from="0%" to="100%" dur="8s" repeatCount="indefinite"/>
</textPath>
</text>
</svg>
```
---
## Example 12: Morphing Shape
Shape morphing between states:
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
<style>
.morph-shape {
fill: #9b59b6;
transition: d 0.5s ease-in-out;
}
.morph-shape:hover {
d: path("M50 10 L90 50 L50 90 L10 50 Z");
}
</style>
<!-- Circle that morphs to diamond on hover -->
<path class="morph-shape" d="M50 10 A40 40 0 1 1 50 90 A40 40 0 1 1 50 10"/>
<!-- Alternative using SMIL animation -->
<path fill="#3498db" transform="translate(0, 0)">
<animate attributeName="d"
values="M50 10 A40 40 0 1 1 50 90 A40 40 0 1 1 50 10;
M50 10 L90 50 L50 90 L10 50 Z;
M50 10 A40 40 0 1 1 50 90 A40 40 0 1 1 50 10"
dur="3s"
repeatCount="indefinite"/>
</path>
</svg>
```
```
### references/reference.md
```markdown
# SVG Reference Documentation
Extended API reference for SVG elements, attributes, and SVGO configuration.
---
## SVG Element Reference
### Container Elements
**svg**: Root container element. Attributes include xmlns (required for standalone), viewBox, width, height, preserveAspectRatio, and x/y for nested SVGs.
**g**: Group element for organizing content. Supports transform, opacity, and presentation attributes that inherit to children.
**defs**: Container for reusable definitions. Content inside defs is not rendered directly. Used for gradients, patterns, filters, symbols, and markers.
**symbol**: Defines reusable graphic with its own viewBox. Never rendered directly. Instantiated via use element. Supports viewBox and preserveAspectRatio.
**use**: References and renders content defined elsewhere. Attributes include href (or xlink:href for legacy), x, y, width, height. Inherits styles but cannot modify internal elements directly.
**a**: Hyperlink wrapper for SVG content. Attributes include href, target, rel. Wraps any SVG element to make it clickable.
**switch**: Conditional rendering based on feature support. Children evaluated in order, first match rendered. Uses requiredFeatures, requiredExtensions, systemLanguage.
**foreignObject**: Embeds non-SVG content like HTML. Attributes include x, y, width, height. Useful for complex text layouts or HTML form elements within SVG.
---
## Shape Element Reference
### rect
Rectangle with optional rounded corners.
Required attributes: width, height
Optional attributes: x, y (default 0), rx, ry (corner radii)
Special cases: If only rx specified, ry equals rx. Maximum rx is half of width.
### circle
Circle defined by center and radius.
Required attributes: cx, cy, r
All attributes default to 0. Radius of 0 produces no visible circle.
### ellipse
Ellipse defined by center and two radii.
Required attributes: cx, cy, rx, ry
rx for horizontal radius, ry for vertical radius.
### line
Straight line between two points.
Required attributes: x1, y1, x2, y2
Must have stroke attribute to be visible (no fill).
### polyline
Connected series of line segments.
Required attribute: points (space or comma-separated coordinate pairs)
Example: points="0,0 10,20 30,10"
Does not automatically close. Typically used with fill="none".
### polygon
Closed shape from connected line segments.
Required attribute: points (same format as polyline)
Automatically closes path from last point to first.
### path
Most powerful shape element using path commands.
Required attribute: d (path data string)
Supports all drawing operations through command letters.
---
## Path Command Reference
### Move Commands
M x y: Absolute move to coordinates (x, y). Starts new subpath.
m dx dy: Relative move by offset (dx, dy) from current position.
### Line Commands
L x y: Absolute line to coordinates (x, y).
l dx dy: Relative line by offset from current position.
H x: Horizontal line to absolute x coordinate. Y unchanged.
h dx: Horizontal line by relative offset. Y unchanged.
V y: Vertical line to absolute y coordinate. X unchanged.
v dy: Vertical line by relative offset. X unchanged.
### Close Command
Z or z: Closes current subpath by drawing line to starting point.
### Cubic Bezier Commands
C x1 y1 x2 y2 x y: Cubic bezier curve.
- (x1, y1): First control point
- (x2, y2): Second control point
- (x, y): End point
c: Relative version with all offsets.
S x2 y2 x y: Smooth cubic bezier.
- First control point reflected from previous curve
- (x2, y2): Second control point
- (x, y): End point
s: Relative version.
### Quadratic Bezier Commands
Q x1 y1 x y: Quadratic bezier curve.
- (x1, y1): Control point
- (x, y): End point
q: Relative version.
T x y: Smooth quadratic bezier.
- Control point reflected from previous curve
- (x, y): End point
t: Relative version.
### Arc Command
A rx ry rotation large-arc sweep x y: Elliptical arc.
- rx: X-axis radius
- ry: Y-axis radius
- rotation: X-axis rotation in degrees
- large-arc: 0 for smaller arc, 1 for larger arc
- sweep: 0 for counter-clockwise, 1 for clockwise
- (x, y): End point
a: Relative version (end point relative).
---
## Text Element Reference
### text
Primary text container element.
Positioning: x, y for starting position. Multiple values create multiple text positions.
Styling: font-family, font-size, font-weight, font-style, text-decoration.
Alignment: text-anchor (start, middle, end), dominant-baseline (auto, middle, hanging, text-top).
### tspan
Inline text span for styling portions of text.
Inherits from parent text element. Can override any text attribute.
Supports dx, dy for relative positioning from previous character.
### textPath
Text rendered along a path shape.
Required: href pointing to path element.
Attributes: startOffset (percentage or length along path), method (align, stretch), spacing (auto, exact).
---
## Gradient Reference
### linearGradient
Linear color transition along a line.
Direction attributes: x1, y1 (start), x2, y2 (end). Values 0% to 100% or absolute units.
Common directions:
- Horizontal: x1="0%" y1="0%" x2="100%" y2="0%"
- Vertical: x1="0%" y1="0%" x2="0%" y2="100%"
- Diagonal: x1="0%" y1="0%" x2="100%" y2="100%"
gradientUnits: userSpaceOnUse (absolute) or objectBoundingBox (percentage, default).
spreadMethod: pad (default), reflect, repeat for colors beyond gradient bounds.
### radialGradient
Radial color transition from center outward.
Position attributes: cx, cy (center), r (radius), fx, fy (focal point).
Focal point creates offset highlight effect when different from center.
gradientUnits and spreadMethod same as linearGradient.
### stop
Color stop within gradient.
Required: offset (0% to 100% or 0 to 1).
Color: stop-color (color value), stop-opacity (0 to 1).
---
## Filter Reference
### filter
Container for filter operations.
Size attributes: x, y, width, height define filter region (default: -10%, -10%, 120%, 120%).
filterUnits: userSpaceOnUse or objectBoundingBox.
primitiveUnits: userSpaceOnUse or objectBoundingBox for child primitives.
### Filter Primitives
**feGaussianBlur**: Blur effect.
- in: Input (SourceGraphic, SourceAlpha, or previous result)
- stdDeviation: Blur amount (single value or "x y")
- result: Output name
**feOffset**: Offset transformation.
- in: Input
- dx, dy: Offset amounts
- result: Output name
**feColorMatrix**: Color transformation.
- in: Input
- type: matrix, saturate, hueRotate, luminanceToAlpha
- values: Matrix values or single value for non-matrix types
**feBlend**: Blend two inputs.
- in, in2: Two inputs
- mode: normal, multiply, screen, darken, lighten, overlay
**feComposite**: Combine two inputs using Porter-Duff operations.
- in, in2: Two inputs
- operator: over, in, out, atop, xor, arithmetic
**feMerge**: Layer multiple inputs.
- Contains feMergeNode children, each with in attribute
- Renders in order (first at bottom)
**feDropShadow**: Shorthand for drop shadow effect.
- dx, dy: Shadow offset
- stdDeviation: Blur amount
- flood-color: Shadow color
- flood-opacity: Shadow opacity
**feFlood**: Fill with solid color.
- flood-color: Color value
- flood-opacity: Opacity value
**feImage**: Insert external image or SVG reference.
- href: Image source
- preserveAspectRatio: Aspect ratio handling
**feMorphology**: Erode or dilate shapes.
- operator: erode, dilate
- radius: Effect amount
**feTurbulence**: Generate noise pattern.
- type: turbulence, fractalNoise
- baseFrequency: Noise frequency
- numOctaves: Detail level
- seed: Random seed
**feDisplacementMap**: Distort using another image.
- in: Input to distort
- in2: Displacement map
- scale: Distortion amount
- xChannelSelector, yChannelSelector: R, G, B, or A
---
## Clipping and Masking Reference
### clipPath
Hard-edged clipping region.
clipPathUnits: userSpaceOnUse or objectBoundingBox.
Content: Any shape elements define clip region. Union of all shapes.
Usage: clip-path="url(#clip-id)" on target element.
### mask
Soft-edged masking with alpha channel.
maskUnits: userSpaceOnUse or objectBoundingBox.
maskContentUnits: userSpaceOnUse or objectBoundingBox for child elements.
Content: Shapes where white reveals, black conceals, gray partially reveals.
Usage: mask="url(#mask-id)" on target element.
---
## SVGO Plugin Reference
### preset-default
Collection of safe default optimizations. Includes:
- cleanupAttrs: Remove newlines, trailing spaces
- removeDoctype: Remove DOCTYPE
- removeXMLProcInst: Remove XML declaration
- removeComments: Remove comments
- removeMetadata: Remove metadata
- removeTitle: Remove title (disable for accessibility)
- removeDesc: Remove desc (disable for accessibility)
- removeUselessDefs: Remove empty defs
- removeEditorsNSData: Remove editor metadata
- removeEmptyAttrs: Remove empty attributes
- removeHiddenElems: Remove hidden elements
- removeEmptyText: Remove empty text
- removeEmptyContainers: Remove empty containers
- removeViewBox: Remove viewBox when possible (often disable)
- cleanupEnableBackground: Remove enable-background
- convertStyleToAttrs: Convert style to attributes
- convertColors: Optimize color values
- convertPathData: Optimize path data
- convertTransform: Optimize transforms
- removeUnknownsAndDefaults: Remove unknown elements
- removeNonInheritableGroupAttrs: Clean group attributes
- removeUselessStrokeAndFill: Remove useless stroke/fill
- removeUnusedNS: Remove unused namespaces
- cleanupIds: Minify IDs
- cleanupNumericValues: Round numeric values
- moveElemsAttrsToGroup: Consolidate attributes
- moveGroupAttrsToElems: Distribute attributes
- collapseGroups: Merge nested groups
- mergePaths: Merge adjacent paths
- sortAttrs: Sort attributes
- sortDefsChildren: Sort defs children
### Individual Plugins
**prefixIds**: Add prefix to IDs to avoid conflicts.
- prefix: Custom prefix string or function
- delim: Delimiter between prefix and ID
**removeAttrs**: Remove specific attributes.
- attrs: Array of attribute patterns to remove
**addAttributesToSVGElement**: Add attributes to root svg.
- attributes: Object of attributes to add
**removeAttributesBySelector**: Remove attributes matching selector.
- selector: CSS selector
- attributes: Attributes to remove
**removeDimensions**: Remove width/height, keep viewBox.
**removeScriptElement**: Remove script elements.
**removeStyleElement**: Remove style elements.
**removeXMLNS**: Remove xmlns from root (for inline SVG).
**reusePaths**: Convert repeated paths to use elements.
**convertShapeToPath**: Convert shapes to path elements.
---
## Presentation Attributes Reference
### Fill Attributes
fill: Paint color (color value, none, url(#gradient-id))
fill-opacity: Opacity (0 to 1)
fill-rule: Winding rule (nonzero, evenodd)
### Stroke Attributes
stroke: Stroke color (color value, none, url(#gradient-id))
stroke-width: Line width (length)
stroke-opacity: Opacity (0 to 1)
stroke-linecap: Line end style (butt, round, square)
stroke-linejoin: Corner style (miter, round, bevel)
stroke-dasharray: Dash pattern (length list, none)
stroke-dashoffset: Dash offset (length)
stroke-miterlimit: Miter limit ratio (number)
### Opacity and Visibility
opacity: Element opacity (0 to 1)
visibility: Visibility (visible, hidden, collapse)
display: Display (inline, block, none)
### Transform
transform: Transformation functions
Functions:
- translate(x, y): Move by offset
- scale(x, y): Scale by factor
- rotate(angle, cx, cy): Rotate around point
- skewX(angle): Skew along X axis
- skewY(angle): Skew along Y axis
- matrix(a, b, c, d, e, f): Transformation matrix
transform-origin: Origin point for transformations
### Color and Painting
color: Current color (inheritable)
color-interpolation: Color space (auto, sRGB, linearRGB)
color-interpolation-filters: Filter color space
paint-order: Paint order (fill, stroke, markers)
### Markers
marker-start: Marker at path start
marker-mid: Marker at path vertices
marker-end: Marker at path end
---
## Coordinate System Reference
### viewBox
Format: "min-x min-y width height"
Defines the coordinate system for SVG content. Content scales to fit width/height while preserving aspect ratio (by default).
### preserveAspectRatio
Format: "align meetOrSlice"
Align values:
- none: No uniform scaling
- xMinYMin: Align to top-left
- xMidYMin: Align to top-center
- xMaxYMin: Align to top-right
- xMinYMid: Align to center-left
- xMidYMid: Align to center (default)
- xMaxYMid: Align to center-right
- xMinYMax: Align to bottom-left
- xMidYMax: Align to bottom-center
- xMaxYMax: Align to bottom-right
meetOrSlice:
- meet: Entire viewBox visible (letterboxing)
- slice: Fill viewport (cropping)
### Units
Absolute units: px, pt, pc, mm, cm, in
Relative units: em, ex, % (percentage of viewBox)
User units: Numbers without unit (same as px)
```