SVG Sprite Icon System Guide
Complete guide to using SVG sprites for optimal icon management across multiple projects.
Why SVG Sprites?
SVG sprites are the optimal approach for managing icons:
Performance Benefits
- ✅ Single HTTP Request - One request per sprite file (vs. one per icon)
- ✅ Better Caching - Browser caches the entire sprite
- ✅ Smaller Total Size - Shared definitions reduce file size
- ✅ Faster Page Loads - Fewer network requests
Build Benefits
- ✅ No Build Processing - Icons are static files
- ✅ Zero Build Impact - Adding icons doesn't slow builds
- ✅ No Bundling - Icons aren't bundled into JavaScript
- ✅ Easy Updates - Just edit SVG file, refresh browser
Maintenance Benefits
- ✅ Version Control Friendly - Single file per icon set
- ✅ CDN Compatible - Can be served from CDN
- ✅ Framework Agnostic - Works with any framework
- ✅ Easy Collaboration - Designers can edit SVG directly
Architecture
Library Level (Common Icons)
packages/ui/src/icons/
└── common-icons.svg (only icons used across multiple projects)Project Level (Project Icons)
your-project/
└── public/
└── svg-icons.svg (all project-specific icons)Sprite File Structure
A sprite file contains multiple icon definitions as <symbol> elements:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<!-- Icon 1 -->
<symbol id="icon-name-1" viewBox="0 0 24 24" fill="none">
<path d="..." fill="currentColor"/>
</symbol>
<!-- Icon 2 -->
<symbol id="icon-name-2" viewBox="0 0 24 24" fill="none">
<path d="..." stroke="currentColor" stroke-width="2"/>
</symbol>
</defs>
</svg>Key Points
- Each icon is a
<symbol>element idattribute is the icon nameviewBoxdefines the coordinate system- Use
currentColorfor fill/stroke (allows color customization)
Setup
1. Create Project Sprite File
Create public/svg-icons.svg:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="project-dashboard" viewBox="0 0 24 24" fill="none">
<path d="M3 3h18v18H3V3z" stroke="currentColor" stroke-width="2"/>
</symbol>
</defs>
</svg>2. Register Sprite
In main.js:
import { registerSprite } from '@ftx/ui';
// Register project sprite (no prefix for project icons)
registerSprite('/svg-icons.svg', {
prefix: '', // No prefix - these are project icons
priority: 20
});3. Use Icons
<!-- Project icon (no prefix needed) -->
<FTxIcon name="dashboard" svg-size="24px" />Multiple Sprite Sources
Register multiple sprites for different icon sets:
import { registerSprite } from '@ftx/ui';
// Common icons (highest priority)
registerSprite('/icons/common-icons.svg', {
prefix: 'ftx-',
priority: 10
});
// Navigation icons
registerSprite('/icons/nav-icons.svg', {
prefix: 'nav-',
priority: 20
});
// Project icons (default)
registerSprite('/svg-icons.svg', {
priority: 30
});Priority System
- Lower priority number = higher priority
- Component searches sprites in priority order
- First matching sprite is used
Adding Icons
Adding to Project Sprite
Edit sprite file:
svg<symbol id="my-new-icon" viewBox="0 0 24 24" fill="none"> <path d="..." fill="currentColor"/> </symbol>Save file
Refresh browser - icon is immediately available!
No build needed!
Adding to Common Sprite (Library)
Important: Common icons are stored ONLY in the common-icons.svg sprite file. Individual SVG files are not used for common icons.
- Edit
packages/ui/src/icons/common-icons.svg - Add a new
<symbol>element withftx-prefix:
<symbol id="ftx-new-icon" viewBox="0 0 24 24" fill="none">
<path d="..." stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>Key points:
- Use
<symbol>element (not<svg>) idattribute must match icon name (e.g.,ftx-new-icon)- Use
currentColorfor fill/stroke - Include
viewBoxattribute (typically0 0 24 24)
- Rebuild library
- The sprite file will be included in the distribution
Note: The icon-registry.js file is for project-specific icons registered dynamically. Common library icons are served via the sprite file only.
Best Practices
1. Icon Naming
- Library icons: Use
ftx-prefix in sprite files (internal format). When using icons, useftx:prefix format (e.g.,ftx:column) - Project icons: No prefix needed in sprite files (e.g.,
dashboard,settings) - Use kebab-case:
dashboard,nav-settings,ftx-column - Avoid conflicts between library and project icons
Important:
- Library icons (
ftx:) are always in sprite files withftx-prefix - Project icons (no prefix) can be in sprite files OR registered via
registerIcon() - Icons registered via
registerIcon()take priority over sprite files
2. SVG Optimization
- Use
currentColorfor fill/stroke - Include
viewBoxattribute - Remove unnecessary attributes
- Optimize paths
- Use consistent viewBox (e.g.,
0 0 24 24)
3. Sprite Organization
Option 1: Single Sprite (Recommended for Small Projects)
public/svg-icons.svg (all project icons)Option 2: Multiple Sprites (Recommended for Large Projects)
public/
├── nav-icons.svg (navigation icons)
├── action-icons.svg (action buttons)
├── status-icons.svg (status indicators)
└── svg-icons.svg (general icons)4. Color Customization
Always use currentColor:
<!-- Good -->
<symbol id="icon" viewBox="0 0 24 24" fill="none">
<path d="..." fill="currentColor"/>
</symbol>
<!-- Bad -->
<symbol id="icon" viewBox="0 0 24 24">
<path d="..." fill="#000000"/>
</symbol>Then customize in component:
<FTxIcon name="icon" svg-size="24px" svg-color="#1976d2" />Performance Comparison
| Approach | HTTP Requests | Bundle Size | Build Time | Cache |
|---|---|---|---|---|
| Individual SVGs | N icons | Large | Slow | Poor |
| Inline SVGs | 0 | Large | Slow | N/A |
| SVG Sprites | 1-2 | Small | None | Excellent |
Troubleshooting
Icon Not Showing
Check sprite file is accessible:
- Open
/svg-icons.svgin browser - Verify it's in
publicfolder
- Open
Verify symbol ID:
svg<symbol id="my-icon" ...> <!-- Must match name="my-icon" -->Check sprite registration:
javascriptimport { getSpriteSources } from '@ftx/ui'; console.log(getSpriteSources());
Icon Color Not Changing
- Ensure SVG uses
currentColor - Use
svg-colorprop (notcolor)
Multiple Sprites Not Working
- Check priority order
- Verify icon name matches symbol ID
- Use
sprite-pathprop to force specific sprite
Advanced Usage
Custom Sprite Path
Override sprite lookup:
<FTxIcon
name="custom-icon"
svg-size="24px"
sprite-path="/custom-icons.svg"
/>Disable Sprite (Use Inline)
<FTxIcon
name="ftx:icon"
svg-size="24px"
:use-sprite="false"
/>Migration from Other Approaches
From Individual SVG Files
- Combine all SVGs into one sprite file
- Convert each SVG to a
<symbol>element - Register sprite
- Update component usage
From Inline SVGs
- Extract SVG content
- Add to sprite as
<symbol> - Register sprite
- Use
FTxIconcomponent
Related
- FTxIcon Component - Component documentation
- Icon Setup Example - Step-by-step setup