At build time, ship one SVG sprite containing only the icon geometry your app uses.
|
8,300+ Icons Lucide + Tabler through one package |
Build-Time Sprite Ship only the icon geometry your app uses |
Zero Runtime Icon Overhead Production renders native <use> references
|
|
One React API Use the same component model across icon sets |
~70% Smaller Compressed HTML Current 135-icon demo |
Custom Icons Add your own SVGs to the same sprite |
Most React icon packages make you choose an icon set up front, then ship each icon as component-level SVG geometry.
React Zero Icon Sprite takes a different approach:
- One package: Lucide and Tabler share one React API, with more icon sets able to join the same catalog over time.
- Build-time discovery:
zero-iconsscans your source and finds the icons your app actually uses. - One production sprite: Used built-in icons and your custom SVGs are compiled into a single cacheable sprite.
- Small production markup: Icon components render native
<svg><use /></svg>references instead of repeating SVG geometry.
You can choose from thousands of icons during development while production ships only the geometry your application needs.
npm install @react-zero-ui/icon-spriteReact 17+ is supported. The zero-icons build step requires Node.js 22.18+ on Node 22, or Node.js 24.11+.
import { ArrowRight, Mail } from "@react-zero-ui/icon-sprite";
<ArrowRight size={24} className="text-gray-600" />
<Mail width={24} height={24} />Caution
Run this before your app build so the sprite exists.
npx zero-iconsOr add it to your package.json:
{
"scripts": {
"prebuild": "zero-icons",
"build": "your build command"
}
}That's it. zero-icons scans your source and writes public/icons.svg before your application build.
Note
Style the outer <svg> through props or className. Descendant selectors such as .icon path apply only to development's inline SVGs; production sprites use an isolated shadow tree.
import { ArrowRight, Mail } from "@react-zero-ui/icon-sprite";
<ArrowRight size={24} className="text-gray-600" />
<Mail width={24} height={24} />tabler icons are imported with the Icon prefix, e.g. IconBrandGithub
import { IconBrandGithub, IconHeart } from "@react-zero-ui/icon-sprite";
<IconBrandGithub size={24} className="text-gray-600" />
<IconHeart width={24} height={24} />Use the Filled suffix for Tabler's filled designs. Color follows currentColor, so text-color classes and the color prop work in development and production.
import { IconHeartFilled, IconStarFilled } from "@react-zero-ui/icon-sprite";
<IconHeartFilled size={24} className="text-red-500" />
<IconStarFilled size={24} color="gold" />Used outline and filled icons share the same production sprite. Filled components are available for Tabler's filled catalog.
Place SVGs anywhere under your app's public/ directory and pass their root-relative URLs to <CustomIcon />:
Tip
public/
brand/
logo.svgimport { CustomIcon } from "@react-zero-ui/icon-sprite";
<CustomIcon src="/brand/logo.svg" size={24} />The required src prop replaces name. The build includes only referenced SVGs. Write src as an inline string, such as src="/brand/logo.svg" or src={"/brand/logo.svg"}, after any JSX spreads. Variables, computed expressions, remote URLs, and symlinks are unsupported. Missing files and paths targeting the generated sprite fail the build.
Note
Development fetches the source SVG and displays it inline, so a brief flash may occur before loading. Production uses the sprite. Style the outer SVG; descendant CSS selectors cannot reach artwork inside an external sprite.
Most apps need no configuration. If your source lives somewhere other than src, app, or pages, add zero-ui.config.ts:
import type { ZeroUIConfig } from "@react-zero-ui/icon-sprite"
export default {
ROOT_DIR: "frontend",
} satisfies ZeroUIConfigThe config also supports scan exclusions, package import names, and sprite output locations. Custom SVGs use their src paths under public/; no custom icon directory setting is needed.
See how development and production rendering differ
Generated icon components follow this shape:
export function ArrowRight(props) {
if (process.env.NODE_ENV !== "production") {
return <svg {...props}>{/* packaged SVG geometry */}</svg>
}
return <svg {...props}><use href="/icons.svg#arrow-right" /></svg>
}This ensures:
- Development uses inline SVG geometry
- Familiar props such as
size,strokeWidth, andclassName - Built-in icons do not depend on fetching the production sprite during development
- Production reuses shared geometry through the sprite
Production icons compile to native SVG <use> references with no icon geometry or icon-library runtime shipped to the client.
At build time:
zero-iconsscans.js,.jsx,.ts, and.tsxsource with Babel AST traversal- Named imports are resolved across the package-owned icon catalog
- Only used built-in icon geometry is selected from Lucide and Tabler
- Only custom SVGs referenced through static
<CustomIcon src="..." />paths are added to that sprite - The final sprite is written to
public/icons.svg - Production icon wrappers render
<use href="/icons.svg#icon-id" />
The CLI is backed by the package's Node build API. It discovers project configuration, scans icon usage, resolves packaged SVG data, and atomically writes the sprite without modifying the installed package.
Part of the React Zero-UI ecosystem.
Created by and maintained by Serbyte Development