About svg-skill
svg-skill is a guide to writing SVG source directly for development and design work involving vector graphics. It organizes drawing, accessibility, validation, and delivery guidance by scenario, and specifies not to use image-generation tools.
Key features
- 01Covers icons, logos, illustrations, charts, and flowcharts
- 02Provides SVG structure and drawing rules
- 03Includes accessibility guidance and quality checks
- 04Supports standalone SVG, React, Vue, and CSS deliverables
- 05Batch-validate SVG files with a script
Use cases
- 01Create UI icons, logos, or app icons
- 02Draw flowcharts, architecture diagrams, or charts
- 03Deliver SVG graphics as React or Vue components
- 04Prepare inline SVG graphics for web pages or email
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ linyaosky/ svg-skill --skill svg-skillAfter installing, type/svg-skillin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
CONTRIBUTING.md.gitignorereference.mdscenarios.mdexamples.mdLICENSEREADME.mdinstall.shscripts/validate.shtest-output/TEST.mdpreview.htmlrun-tests.shtest-output/12-integration/BellIcon.tsxMailIcon.vuedemo.cssDetails
From the project READMEsvg-skill
Write SVG source directly. Do not use image generation tools.
Scenario index
Match user intent, then pick a path. Details in scenarios.md, examples in examples.md.
| Scenario | viewBox | Key technique | Deliverable |
|---|---|---|---|
| UI icons (outline/filled) | 0 0 24 24 | currentColor, uniform stroke-width | file / React component |
| Multi-color icons | 0 0 24 24 | separate paths + fixed fill | file |
| Logo / brand mark | brand-specific | path outlines, safe margin | SVG + optional favicon |
| Favicon / app icon | 0 0 32 32 | minimal, high contrast | file |
| Illustration / empty state | 0 0 100 100+ | flat shapes | SVG / inline |
| Flowchart / architecture | content-based | marker arrows, grid alignment | UTF-8 file |
| Charts (bar/line/pie) | data-based | coords from scale | title + desc |
| Progress ring / bar | 0 0 24 24 or bar | stroke-dasharray or rect width | animatable |
| Avatar placeholder | 0 0 40 40 | circle + letter / person path | currentColor |
| Badge / label | text-based | rounded rect + text | brand colors |
| Wave divider | 0 0 1200 120 | bezier path, preserveAspectRatio="none" | full-width |
| Map pin | 0 0 24 24 | teardrop path + center dot | theme or fixed color |
| Sprite sheet | per symbol | <symbol> + <use href="#id"> | single sprite.svg |
| CSS background / mask | same as icons | external file or data URI | CSS snippet |
| Loading animation | 0 0 24 24 | CSS @keyframes or stroke-dash | inline SVG |
| Hover interaction | any | CSS :hover on fill/stroke/transform | inline + style |
| Clip shapes | container-based | <clipPath> / <mask> | defs reference |
| Shadow / blur | any | <filter> feDropShadow / feGaussianBlur | defs reference |
| Pattern texture | small unit | <pattern> tile | defs reference |
| React / Vue component | 0 0 24 24 | spread props, camelCase attrs | .tsx / .vue |
| Email inline | minimal | no style/animation/external refs | compact snippet |
Poor fit for SVG: photorealism, complex bitmap textures, overly detailed illustration → explain limits, suggest raster or simplified style.
Workflow
- [ ] 1. Pick scenario and deliverable from index
- [ ] 2. Set viewBox, style, colors (currentColor vs brand)
- [ ] 3. Draw: compose shapes → paths; shared assets in <defs>
- [ ] 4. A11y: decorative aria-hidden / informative title+desc
- [ ] 5. Minimize; non-ASCII text → UTF-8 + XML declaration
- [ ] 6. Write file; run validate.sh
Skeleton templates
Icon only (no text):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" aria-hidden="true">
</svg>
Non-ASCII text (CJK, etc.):
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 120" role="img" aria-labelledby="title">
<title id="title">Diagram title</title>
</svg>
Full-width decor (waves, etc.):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none" aria-hidden="true">
</svg>
Drawing rules
- viewBox defines logic coords; display size via CSS
width/height - Monochrome UI assets default to
currentColor - Outline icons —
stroke-width="2"stroke-linecap="round"stroke-linejoin="round" - Shared defs — gradients, arrows, patterns, filters in
<defs>; short uniqueids - Charts — compute margins and scale first; summarize data in title/desc
- Animation — prefer CSS; SMIL only for simple cases
- Flat by default — gradients/shadows only when needed
Quality checklist
-
xmlns+viewBox - Non-ASCII text → UTF-8 + XML declaration
- No placeholder paths or editor metadata
-
ids unique within file (sprites especially) - Charts have title; decorative icons use aria-hidden
- File opens and previews standalone
bash scripts/validate.sh path/to/dir/
xmllint --noout file.svg # required for non-ASCII text
Deliverables
| Form | Approach |
|---|---|
Standalone .svg | write to assets/ etc. |
| Sprite | multiple <symbol> in one file; document <use> usage |
| React | export function XIcon(props: SVGProps<SVGSVGElement>) + spread |
| Vue | <template><svg ...></svg></template> |
| CSS background | background: url(...) or inline data URI |
| CSS mask | -webkit-mask: url(...); shape needs solid fill area |
| Inline HTML | raw <svg> fragment, no wrapper div (unless requested) |
Do not
- Use
<image>to fake vectors with bitmaps (unless explicitly requested) - Use image generation for simple vectorizable graphics
- Leave empty paths / TODO placeholders
- Omit UTF-8 declaration for non-ASCII text
- Add complex animation or external deps for email use cases
Tools & docs
| Resource | Description |
|---|---|
| scenarios.md | Per-scenario step-by-step |
| reference.md | Path syntax, defs, frameworks |
| examples.md | Full code samples |
| scripts/validate.sh | Batch validation |