react-native-font-icon
v0.2.1
Published
Automatically generates icon fonts (TTF) from SVGs for React Native, providing faster rendering than raw SVGs.
Downloads
26
Readme
react-native-font-icon
Generate icon fonts (TTF) from SVG files for React Native, then render icons as plain <Text> instead of runtime SVG. This is typically much faster than react-native-svg for large icon grids/lists.
Table of contents
- What this library does
- Installation
- CLI — generate fonts from SVGs
- Add fonts to your React Native app
- Runtime API — render icons in your app
- Benchmarks
- Limitations & compatibility
- Roadmap / TODO
- Contributing & credits
- License
What this library does
This project focuses on SVG → font generation and a small runtime API to render the result. It is not aiming to support every possible SVG feature.
Blog post: I Built an Icon Font Library for React Native — Here's What I Learned — motivation, approach, and real-world benchmark results.
| Icon type | Status | CLI command |
|---|---|---|
| Monochrome (filled/solid SVG) | Supported (recommended) | generate:monochrome |
| Stroke/outline SVG → monochrome | Experimental (requires Inkscape) | generate:monochrome --sanitize |
| Colorful SVG → color font | Experimental (requires Python + nanoemoji) | generate:colors |
Installation
yarn add react-native-font-icon
# or
npm install react-native-font-iconNode 22+ is required. The CLI entrypoint is a
.tsfile and relies on modern Node's TypeScript support.
CLI — generate fonts from SVGs
The package ships a CLI binary named generate. You invoke it through npx (or yarn):
npx --package react-native-font-icon generate <command> [options]generate:monochrome
Generate a monochrome TTF font + glyph map from solid/filled SVG icons. This is the recommended path for most use cases.
Alias: generate:font
npx --package react-native-font-icon generate generate:monochrome \
--src ./icons \
--dest ./src/assets/fonts/common \
--font-name my-iconsOutput files:
| File | Description |
|---|---|
| <dest>/<font-name>.ttf | The generated monochrome font |
| <dest>/<font-name>.json | Glyph map ({ "icon-name": <codepoint>, ... }) |
generate:monochrome + sanitize (experimental)
If your SVGs use strokes instead of fills, you can try the sanitize pipeline. It uses Inkscape to convert strokes to paths before compiling the font.
Requires: Inkscape CLI installed on your system.
npx --package react-native-font-icon generate generate:monochrome \
--src ./icons \
--dest ./src/assets/fonts/common \
--font-name my-icons-sanitized \
--sanitize \
--sanitize-engine inkscapeYou can also point to a custom Inkscape binary and enable an extra outline pass:
npx --package react-native-font-icon generate generate:monochrome \
--src ./icons \
--dest ./src/assets/fonts/common \
--font-name my-icons-sanitized \
--sanitize \
--sanitize-engine inkscape \
--inkscape /usr/local/bin/inkscape \
--inkscape-outlineOutput quality depends heavily on the source SVGs. Best results come from simple, well-structured stroke icons.
generate:colors (experimental)
Generate platform-specific color fonts (Android uses COLR, iOS uses SBIX). This produces separate TTF files per platform and a shared glyph map.
Requires: Python 3 + dependencies.
Step 1 — install Python dependencies:
python3 -m pip install -r node_modules/react-native-font-icon/python-utils/requirements.txtStep 2 — generate:
npx --package react-native-font-icon generate generate:colors \
--src ./color-icons \
--dest ./src/assets/fonts/common \
--platform-base-path ./src/assets/fonts \
--font-name my-color-iconsOutput files:
| File | Description |
|---|---|
| <dest>/<font-name>-glyphmap.json | Shared glyph map |
| <platform-base-path>/ios/<font-name>.ttf | iOS color font (SBIX) |
| <platform-base-path>/android/<font-name>.ttf | Android color font (COLR) |
The color pipeline automatically skips some unsupported SVG patterns (e.g. certain
clipPath+gradientcombinations).
CLI options reference
generate:monochrome / generate:font
| Option | Required | Default | Description |
|---|---|---|---|
| --src <path> | Yes | — | Folder containing SVG icons |
| --dest <path> | Yes | — | Destination folder for the .ttf and .json |
| --font-name <name> | No | Derived from folder name | Font family name and output file name |
| --max <count> | No | All icons | Limit number of icons (useful for quick tests) |
| --sanitize | No | false | Enable SVG sanitization before compilation |
| --sanitize-engine <engine> | No | inkscape | Sanitization engine (only inkscape is supported) |
| --inkscape <path> | No | Auto-detected | Custom path to Inkscape binary |
| --inkscape-outline | No | false | Run an extra outline pass after Inkscape |
generate:colors
| Option | Required | Default | Description |
|---|---|---|---|
| --src <path> | Yes | — | Folder containing SVG icons |
| --dest <path> | Yes | — | Destination folder for the glyph map |
| --font-name <name> | No | color-family | Font family name |
| --platform-base-path <path> | No | — | Base folder for ios/ and android/ TTF outputs |
| --python <binary> | No | python3 | Python binary to use |
| --max <count> | No | All icons | Limit number of icons |
Both commands also accept positional arguments:
generate:monochrome [src] [dest], but named flags are recommended for clarity.
Add fonts to your React Native app
After generating the .ttf files, you need to make them available to the native runtime.
Option A (recommended) — use react-native-asset:
npx react-native-assetOption B — link fonts manually via iOS Info.plist / Android assets folder, depending on your project setup.
Runtime API — render icons in your app
The library exports the following:
| Export | Type | Description |
|---|---|---|
| IconProvider | Component | Context provider — wraps your app and supplies font data |
| Icon | Component | Renders a single icon as a <Text> element |
| useGetAllIcons | Hook | Returns all icon names for a given font family |
| useFontIconContext | Hook | Returns the full font icon context |
Quick start
import React from 'react';
import { IconProvider, Icon } from 'react-native-font-icon';
// Import the generated glyph map (JSON)
import appIconsGlyphMap from './assets/fonts/common/app-icons.json';
// Define your font families
const fontData = [
{
family: 'app-icons', // must match the font name used in generation
glyphMap: appIconsGlyphMap,
},
];
export default function App() {
return (
<IconProvider fontData={fontData}>
{/* Renders the "home" icon from "app-icons" family */}
<Icon name="home" family="app-icons" style={{ fontSize: 24 }} />
</IconProvider>
);
}IconProvider
Wraps your component tree and provides font data to all Icon components below it.
<IconProvider fontData={fontData}>
{children}
</IconProvider>Props:
| Prop | Type | Required | Description |
|---|---|---|---|
| fontData | FontDataEntry[] \| Record<string, FontDataEntry> | Yes | One or more font families with their glyph maps |
| children | ReactNode | Yes | Your app / component tree |
FontDataEntry shape:
{
family: string; // Font family name (e.g. "app-icons")
glyphMap: Record<string, number>; // { "icon-name": codepoint }
}Behavior:
- The first entry in
fontDatais used as thefallbackFamily. If you omit thefamilyprop onIcon, it will use this fallback. fontDatacan be an array or an object keyed by family name.
Multiple font families:
import monoGlyphMap from './assets/fonts/common/app-icons.json';
import colorGlyphMap from './assets/fonts/common/color-icons-glyphmap.json';
const fontData = [
{ family: 'app-icons', glyphMap: monoGlyphMap },
{ family: 'color-icons', glyphMap: colorGlyphMap },
];
<IconProvider fontData={fontData}>
{/* app-icons is the fallback since it's first */}
<Icon name="home" /> {/* uses "app-icons" */}
<Icon name="star" family="color-icons" /> {/* uses "color-icons" */}
</IconProvider>Icon
Renders a single icon. It is a wrapper around React Native's <Text> component, so all TextProps are supported (e.g. style, onPress, testID).
<Icon name="home" family="app-icons" style={{ fontSize: 24, color: '#333' }} />Props:
| Prop | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Icon name (must exist in the glyph map) |
| family | string | No | Font family to use. Falls back to the first entry in fontData |
| style | TextStyle | No | Standard React Native text styles (fontSize, color, etc.) |
| ...rest | TextProps | — | Any other TextProps are passed through |
Default font size: 32
Error handling:
- If
nameis not found in the glyph map,Iconthrows an error. - If no family is resolved, it renders a fallback "X" character.
useGetAllIcons
Returns an array of all icon names for a given font family. Useful for building icon browsers or pickers.
import { useGetAllIcons } from 'react-native-font-icon';
function IconGrid() {
const allIcons = useGetAllIcons('app-icons');
return (
<FlatList
data={allIcons}
renderItem={({ item }) => <Icon name={item} family="app-icons" />}
/>
);
}Signature: useGetAllIcons(family: string) => string[]
- Returns all keys from the glyph map for that family.
- Returns an empty array if the family is not found.
- Memoized — only recalculates when the family or font data changes.
useFontIconContext
Returns the full font icon context. Use this if you need direct access to font data (e.g. to build custom rendering logic).
import { useFontIconContext } from 'react-native-font-icon';
function DebugInfo() {
const { fontEntries, fallbackFamily, fontEntryByFamily } = useFontIconContext();
console.log('Fallback family:', fallbackFamily);
console.log('Registered families:', fontEntries.map(e => e.family));
return null;
}Returns:
| Field | Type | Description |
|---|---|---|
| fontData | FontGlyphCollection | Original font data as passed to IconProvider |
| fontEntries | ReadonlyArray<FontDataEntry> | Normalized array of all font entries |
| fontEntryByFamily | Map<string, FontDataEntry> | Fast lookup map keyed by family name |
| fallbackFamily | string | The default family (first entry) |
Must be called inside an
IconProvider. Throws if used outside of one.
Benchmarks
Rendering performance measured in the example app (ScrollView grid). Font = this library's <Icon> component (renders via <Text>). SVG = same icons rendered with react-native-svg.
iOS
| Type | Icons | Font (ms) | SVG (ms) | Speedup | |---|---|---|---|---| | Monochrome | 100 | 39.49 | 89.91 | 2.3x | | Monochrome | 500 | 201.82 | 460.28 | 2.3x | | Monochrome | 1000 | 444.93 | 914.80 | 2.1x | | Color | 100 | 41.40 | 238.44 | 5.8x | | Color | 500 | 203.41 | 1,151.28 | 5.7x | | Color | 1000 | 404.22 | 2,319.80 | 5.7x |
Android
| Type | Icons | Font (ms) | SVG (ms) | Speedup | |---|---|---|---|---| | Monochrome | 100 | 79.47 | 141.85 | 1.8x | | Monochrome | 500 | 366.37 | 611.42 | 1.7x | | Monochrome | 1000 | 744.84 | 1,136.28 | 1.5x | | Color | 100 | 87.86 | 300.72 | 3.4x | | Color | 500 | 347.25 | 1,439.93 | 4.1x | | Color | 1000 | 708.55 | 2,733.14 | 3.9x |
Summary: The difference is most noticeable with color icons (up to 5.8x on iOS, 4.1x on Android). For monochrome icons the gap is smaller (1.5x–2.3x). For most apps with a moderate number of icons,
react-native-svgworks perfectly fine.
Limitations & compatibility
- Stroke-based SVGs are not supported by default. The sanitize flow (Inkscape) is experimental.
- Color fonts are experimental but work on both iOS and Android.
- For best results, SVG icons should be solid / filled (no strokes).
- In the example app, this approach successfully transforms roughly ~95% of icons. Failures usually come from stroke usage, unsupported SVG features, or complex path structures.
- For most use cases,
react-native-svgis a great choice and we recommend it. The font approach shows a noticeable improvement mainly with color icons; for monochrome icons the difference is small.
Roadmap / TODO
- [ ] Better solid icon sets — find and bundle higher-quality solid/filled icon packs for the example app (current sets are for demonstration only).
- [ ] Improved fallback mechanism — a smarter runtime fallback that can help with color and stroke icons when font rendering fails (e.g. automatic SVG fallback per icon).
- [ ] Better sanitization pipeline — replace or supplement Inkscape with a lighter, more reliable stroke-to-path engine for the
--sanitizeflow.
Contributions are welcome! Feel free to open a pull request if you'd like to help with any of the above (or anything else).
Contributing & credits
Example app icon packs (for demonstration only, not for commercial use):
- Iconoir — monochrome icons
- Figma community pack — additional monochrome icons
- Flowbite Icons — colorful icons
- SVG Owl — Halloween Scary Vectors
- SVG Owl — Winter Town Filled Vectors
- Streamline HQ — potential future source for solid icons
License
MIT
Made with create-react-native-library
