nuxt-svg-sprite-icon
Version:
A powerful SVG sprite module for Nuxt 3 & 4 that automatically generates SVG sprites from your assets and provides an easy-to-use component for displaying icons.
422 lines (321 loc) ⢠11.7 kB
Markdown
# Nuxt SVG Sprite Icon
<p align="center">
<img width="200px" src="./assets/nuxt-svg-sprite-icon.png" />
</p>
<p align=center>
<a target="_blank" href="https://vuejs.org/" title="vue">
<a target="_blank" href="http://nodejs.org/download/" title="Nuxt version">
<img src="https://img.shields.io/badge/Nuxt-%3E%3D%203.0.0%20%7C%7C%20%5E4.0.0-brightgreen.svg">
</a>
<img src="https://img.shields.io/badge/Vue-%3E%203.0.0-brightgreen.svg">
</a>
<a target="_blank" href="http://nodejs.org/download/" title="Node version">
<img src="https://img.shields.io/badge/Node-%3E%3D%2020.0.0-brightgreen.svg">
</a>
<a target="_blank" href="https://github.com/MikeCheng1208/nuxt-svg-sprite-icon/pulls" title="PRs Welcome">
<img src="https://img.shields.io/badge/PRs-welcome-blue.svg">
</a>
</p>
<p align=center>A powerful SVG sprite module for Nuxt 3 & Nuxt 4 that automatically generates SVG sprites from your assets and provides an easy-to-use component for displaying icons.</p>
<p align="center">
<a target="_blank" href="https://www.npmjs.com/package/nuxt-svg-sprite-icon">
<img src="https://nodei.co/npm/nuxt-svg-sprite-icon.png?downloads=true&downloadRank=true&stars=true" alt="NPM version">
</a>
</p>
## Features
- š **Auto-generated SVG sprites** - Automatically scans and converts SVG files to sprite format
- š **Nested folder support** - Organize your icons in folders for better structure
- šØ **CSS-only styling** - Full control over appearance using CSS classes
- ā” **Hot reload** - Development mode file watching for instant updates
- šÆ **TypeScript support** - Full type safety out of the box
- š **Framework agnostic** - Works seamlessly with UnoCSS, Tailwind, or any CSS framework
- š¦ **Zero configuration** - Works out of the box with sensible defaults
- šŖ¶ **Lightweight** - Minimal API surface with maximum flexibility
- š§ **Enhanced SVG compatibility** - Handles complex SVGs with styles, IDs, and defs
## Quick Setup
1. Add `nuxt-svg-sprite-icon` dependency to your project
```bash
# Using pnpm
pnpm add -D nuxt-svg-sprite-icon
# Using yarn
yarn add --dev nuxt-svg-sprite-icon
# Using npm
npm install --save-dev nuxt-svg-sprite-icon
```
2. Add `nuxt-svg-sprite-icon` to the `modules` section of `nuxt.config.ts`
```js
export default defineNuxtConfig({
modules: [
'nuxt-svg-sprite-icon'
]
})
```
3. Create your SVG assets directory and add some SVG files
```
assets/
svg/
home.svg
search.svg
user/
profile.svg
settings.svg
```
4. Use the SVG icons in your components
```vue
<template>
<div>
<!-- Basic usage -->
<SvgIcon name="home" />
<!-- With CSS classes -->
<SvgIcon name="home" class="w-6 h-6 text-blue-500" />
<!-- Nested folder -->
<SvgIcon name="user/profile" class="w-8 h-8 fill-green-500" />
<!-- Container approach -->
<div class="w-100px h-100px">
<SvgIcon name="search" class="w-full h-full fill-red-500" />
</div>
</div>
</template>
```
That's it! You can now use SVG icons with complete CSS control āØ
## SVG Compatibility
This module has enhanced SVG processing capabilities that handle various types of SVG files:
### ā
Supported SVG Features
- **Inline styles and CSS classes** - Automatically converts `<style>` tags and CSS classes to inline styles
- **Gradients / Paint servers (`url(#...)`)** - Supports `linearGradient` / `radialGradient` (including `fill="url(#...)"` and `stroke="url(#...)"`)
- **Complex defs** - Preserves functional definitions like `clipPath`, `mask`, `pattern`, and `filter`
- **ID conflict resolution** - Automatically prefixes IDs to prevent conflicts between different sprites
- **Various SVG formats** - Works with SVGs from different design tools (Figma, Sketch, Illustrator, etc.)
### Examples of Supported SVG Types
**SVG with CSS styles:**
```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.721 17.39">
<defs>
<style>
.cls-1{fill:#fff}
</style>
</defs>
<path class="cls-1" d="M0 6.3L6 11..."/>
</svg>
```
**SVG with inline fills:**
```xml
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="white" d="M9.84375 16.0469V19.1178..."/>
</svg>
```
**SVG with clipPaths and complex defs:**
```xml
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path fill="white" d="..."/>
</g>
<defs>
<clipPath id="clip0">
<rect width="24" height="24"/>
</clipPath>
</defs>
</svg>
```
**SVG with gradients / paint servers (`url(#...)`):**
```xml
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="paint0_linear" x1="20" y1="0" x2="0" y2="20" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFCF45"/>
<stop offset="1" stop-color="#FFB92A"/>
</linearGradient>
</defs>
<path d="M10 1L12.5 7H19L14 11L16 18L10 14L4 18L6 11L1 7H7.5Z" fill="url(#paint0_linear)"/>
</svg>
```
All these formats are automatically processed and optimized for use in sprite systems while maintaining visual fidelity.
## Configuration
You can configure the module by adding a `svgSprite` section to your `nuxt.config.ts`:
```js
export default defineNuxtConfig({
modules: ['nuxt-svg-sprite-icon'],
svgSprite: {
// Source directory for SVG files
input: '~/assets/svg',
// Output directory for generated sprites
output: '~/assets/sprite/gen',
// Default sprite name (for files in root of input directory)
defaultSprite: 'icons',
// Global CSS class for all svg-icon instances
elementClass: 'svg-icon',
// Whether to optimize SVG files (requires svgo)
optimize: false
}
})
```
### Nuxt 4 Configuration
For Nuxt 4 projects, you can use the new directory structure:
```js
export default defineNuxtConfig({
future: {
compatibilityVersion: 4,
},
modules: ['nuxt-svg-sprite-icon'],
svgSprite: {
// Use app directory for Nuxt 4
input: './app/assets/svg',
output: './app/assets/sprite/gen',
defaultSprite: 'icons',
elementClass: 'svg-icon',
}
})
```
The module automatically detects Nuxt 4 compatibility mode and adjusts paths accordingly.
### Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `input` | `string` | `'~/assets/svg'` | Directory containing original SVG files |
| `output` | `string` | `'~/assets/sprite/gen'` | Directory for generated sprite files |
| `defaultSprite` | `string` | `'icons'` | Name of default sprite (for SVGs in root input directory) |
| `elementClass` | `string` | `'svg-icon'` | Global CSS class applied to all `<SvgIcon>` elements |
| `optimize` | `boolean` | `false` | Enable SVG optimization using SVGO |
## Component API
### SvgIcon Component
The `<SvgIcon>` component is automatically registered and available globally.
#### Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `name` | `string` | - | **Required.** Name of the icon (supports nested paths like `user/example`) |
#### Usage Examples
```vue
<template>
<!-- Basic usage with default 1em size -->
<SvgIcon name="home" />
<!-- Control size with CSS classes -->
<SvgIcon name="home" class="w-6 h-6" />
<SvgIcon name="home" class="w-8 h-8" />
<!-- Control size with font-size -->
<SvgIcon name="home" class="text-2xl" />
<SvgIcon name="home" style="font-size: 3rem;" />
<!-- Control color -->
<SvgIcon name="home" class="text-blue-500" />
<SvgIcon name="home" class="fill-red-600" />
<!-- Nested folder icons -->
<SvgIcon name="user/profile" class="w-10 h-10 text-green-500" />
<!-- Container-based sizing -->
<div class="w-20 h-20">
<SvgIcon name="search" class="w-full h-full fill-purple-500" />
</div>
<!-- Custom styles -->
<SvgIcon name="home" class="custom-icon" />
<!-- Interactive states -->
<SvgIcon
name="home"
class="w-8 h-8 text-blue-500 hover:text-blue-700 transition-colors cursor-pointer"
/>
<!-- Responsive sizing -->
<SvgIcon name="home" class="w-4 h-4 md:w-6 md:h-6 lg:w-8 lg:h-8" />
</template>
<style scoped>
.custom-icon {
width: 3rem;
height: 3rem;
color: #3b82f6;
transition: all 0.2s ease;
}
.custom-icon:hover {
color: #1d4ed8;
transform: scale(1.1);
}
</style>
```
## File Organization
The module supports nested folder structures:
```
assets/svg/
āāā home.svg ā <SvgIcon name="home" />
āāā search.svg ā <SvgIcon name="search" />
āāā user/
ā āāā profile.svg ā <SvgIcon name="user/profile" />
ā āāā settings.svg ā <SvgIcon name="user/settings" />
āāā admin/
āāā dashboard.svg ā <SvgIcon name="admin/dashboard" />
āāā users.svg ā <SvgIcon name="admin/users" />
```
## Development
```bash
# Install dependencies
npm install
# Generate type stubs and prepare development environment
npm run dev:prepare
# Develop with the playground
npm run dev
# Build the playground
npm run dev:build
# Build the module
npm run prepack
# Run type checking
npm run test:types
# Release new version
npm run release
```
## CSS Framework Integration
### With UnoCSS/Tailwind CSS
```vue
<template>
<!-- Size control -->
<SvgIcon name="home" class="w-6 h-6" />
<SvgIcon name="home" class="w-8 h-8" />
<!-- Color control -->
<SvgIcon name="home" class="text-blue-500" />
<SvgIcon name="home" class="fill-red-600" />
<!-- Combined styling -->
<SvgIcon
name="user/profile"
class="w-10 h-10 text-green-500 hover:text-green-700 transition-all duration-200"
/>
<!-- Responsive design -->
<SvgIcon name="home" class="w-4 h-4 sm:w-6 sm:h-6 lg:w-8 lg:h-8" />
<!-- Container-based approach -->
<div class="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center">
<SvgIcon name="home" class="w-8 h-8 text-gray-600" />
</div>
</template>
```
### With Custom CSS
```vue
<template>
<SvgIcon name="home" class="icon-large" />
<SvgIcon name="user/profile" class="icon-animated" />
</template>
<style scoped>
.icon-large {
width: 4rem;
height: 4rem;
color: #3b82f6;
}
.icon-animated {
width: 2rem;
height: 2rem;
transition: transform 0.3s ease;
}
.icon-animated:hover {
transform: rotate(180deg) scale(1.2);
}
</style>
```
## Troubleshooting
### Icons not displaying
1. **Check file paths**: Ensure your SVG files are in the correct directory
2. **Verify build**: Make sure the module generated sprite files in your output directory
3. **Check console**: Look for any error messages in the browser console
4. **Restart dev server**: Try restarting your development server
### Icons appear as squares
This usually indicates that the SVG files have incorrect or missing `viewBox` attributes. The module attempts to extract or generate appropriate viewBox values, but you may need to manually fix your SVG files.
### Size control issues
- Use `width` and `height` CSS properties or utility classes like `w-6 h-6`
- The default size is `1em`, so you can also control size via `font-size`
- For container-based sizing, use `w-full h-full` on the icon
## Performance Considerations
- All sprites are injected into the DOM on page load
- For large icon sets, consider organizing icons into different folders/sprites
- SVG optimization can help reduce file sizes (enable with `optimize: true`)
- The CSS-only approach means no JavaScript is needed for styling
## License
MIT.