Custom icons, duotone and the styling toolkit
Add your own icons, control duotone's two layers from CSS, use the sharp styles, and understand what the Icon Wizard and Pro+ packs change.
Your own icons
// Option A: upload the SVG in the kit UI. Simple, but your icon set now
// lives partly in a vendor's system and is not in your repository.
// Option B: define the icon in your own code. The definition is data, not
// markup, so it lives in version control and works with every SDK.
import { IconDefinition } from '@fortawesome/fontawesome-svg-core';
export const faWarehouse: IconDefinition = {
prefix: 'fas',
iconName: 'warehouse',
icon: [
640, // viewBox width
512, // viewBox height
[], // ligatures
'e001', // unicode: use a private-use code point
'M32 64C14.3 64 0 78.3 0 96v64c0 17.7 14.3 32 32 32H608c17.7 0 32-14.3 32-32V96c0-17.7-14.3-32-32-32H32zm16 192v192H16c-8.8 0-16 7.2-16 16s7.2 16 16 16H624c8.8 0 16-7.2 16-16s-7.2-16-16-16H592V256c0-17.7-14.3-32-32-32H80c-17.7 0-32 14.3-32 32z'
]
};
// A multi-path icon: the last element is an array of path strings.
export const faServerStack: IconDefinition = {
prefix: 'fas',
iconName: 'server-stack',
icon: [512, 512, [], 'e002', [
'M64 32C28.7 32 0 60.7 0 96v64c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64zm0 192c-35.3 0-64 28.7-64 64v64c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V288c0-35.3-28.7-64-64-64H64z'
]]
};
// Register and use exactly like a standard icon
// library.add(faWarehouse, faServerStack);| Definition field | Meaning | Rule |
|---|---|---|
prefix | The style family | fas, far, fab, or your own |
iconName | The name used in markup and lookups | Kebab-case, unique |
| Width, height | The viewBox dimensions | Match your path data exactly |
| Ligatures | Text shortcuts | Usually empty for custom icons |
| Unicode | A code point for the font route | Use the private use area, e000-f8ff |
| Path | One string, or an array of strings | The d attribute contents, without the element |
| Duotone second path | An object with primary and secondary | Only for duotone definitions |
⚠️
Never redefine a code point that Font Awesome already uses, and never reuse one across your own custom icons. On the font route a collision shows the wrong glyph, and in a subset build it can collapse two icons into one. Stay inside the private use area and keep a comment recording which code belongs to which icon.
Duotone and its layers
<!-- A duotone icon has two paths. The second is the secondary layer,
drawn behind, and both are themed with CSS custom properties. -->
<i class="fa-duotone fa-solid fa-house icon"></i>
<style>
.icon {
--fa-primary-color: #4c1d95; /* the front layer */
--fa-secondary-color: #c4b5fd; /* the back layer */
--fa-primary-opacity: 1;
--fa-secondary-opacity: 0.6;
--fa-size: 2rem;
}
/* Swap which layer gets which colour, without changing markup */
.icon--swapped {
--fa-primary-color: #c4b5fd;
--fa-secondary-color: #4c1d95;
}
/* Animated duotone: the layers are real paths, so each can be animated */
.icon--live {
--fa-primary-opacity: 0.4;
--fa-secondary-opacity: 0.25;
transition: --fa-secondary-opacity 300ms ease;
}
.icon--live:hover { --fa-secondary-opacity: 0.9; }
</style><!-- On the web-font route there are no separate layers, so duotone is
approximated with stacked elements. The SVG route needs only one element
and two custom properties. -->
<span class="fa-stack fa-2x" aria-hidden="true">
<i class="fa-duotone fa-solid fa-house fa-stack-2x" style="--fa-secondary-color:#c4b5fd"></i>
</span>
<!-- Pro+ adds Sharp and Sharp Duotone, which have their own family names and
reject the rounded styles. Changing style is a class change: -->
<i class="fa-sharp fa-solid fa-house"></i>
<i class="fa-sharp-duotone fa-solid fa-house"></i>
<!-- Icon Wizard modifiers adjust an existing Pro icon: add a badge, cut a
corner, add a slash. The result is a new icon definition you own, with
its own name and code point. -->| Style | Layers | Family | Availability |
|---|---|---|---|
| Solid | 1 | Font Awesome 7 Free, weight 900 | Free |
| Regular | 1 | Font Awesome 7 Free, weight 400 | Free, limited set |
| Light | 1 | Font Awesome 7 Pro, weight 300 | Pro |
| Duotone | 2 | Font Awesome 7 Duotone | Pro |
| Sharp Solid | 1 | Font Awesome 7 Sharp | Pro |
| Sharp Regular / Light | 1 | Font Awesome 7 Sharp, weight 400 / 300 | Pro |
| Sharp Duotone | 2 | Font Awesome 7 Sharp Duotone | Pro+ |
| Custom uploaded | Any | Your kit's family name | Kit-dependent |
- The duotone secondary layer sits behind the primary. If the icon looks flat, check that the secondary opacity is not zero and the secondary colour is not identical to the primary.
- Custom-property transitions need
@propertydeclarations to interpolate; without them the change is instant rather than animated. - An uploaded custom icon is served from the kit CDN, so it inherits the kit's latency and CSP requirements. A locally defined definition avoids both.
- Sharp styles are a different geometry set, not a rendering option — you cannot turn a rounded Solid icon into a Sharp one with CSS.
/* Registering the properties makes them interpolate rather than snap. */
@property --fa-secondary-opacity {
syntax: "<number>";
inherits: true;
initial-value: 0.4;
}
@property --fa-primary-opacity {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
/* Now a hover transition on the layer opacity is smooth. */
.duotone-hover {
--fa-secondary-opacity: 0.35;
transition: --fa-secondary-opacity 250ms ease-out;
}
.duotone-hover:hover { --fa-secondary-opacity: 1; }Choosing between free, Pro and Pro+
| Need | Free | Pro | Pro+ |
|---|---|---|---|
| Solid icons | About 2,000 | All Solid | All Solid |
| Brands | Yes | Yes | Yes |
| Duotone | No | Yes | Yes |
| Sharp styles | No | Yes | Yes |
| Sharp Duotone, Thumb Icons | No | No | Yes |
| Icon Wizard modifiers | No | Limited | Yes |
| Custom icon uploads | A small number | More | Most |
| Self-hosting the Pro fonts | Not applicable | Your licence permits it in your project | Same |
| A private-use code range for your own icons | Yes | Yes | Yes |
// Self-hosting a Pro package: the same pattern as the free one, using the
// packages your licence grants.
// npm install @fortawesome/pro-solid-svg-icons @fortawesome/pro-duotone-svg-icons
import { library } from '@fortawesome/fontawesome-svg-core';
import { faHouse } from '@fortawesome/pro-solid-svg-icons';
import { faHouse as faHouseDuotone } from '@fortawesome/pro-duotone-svg-icons';
// The same iconName in two styles is resolved by the prefix, so both can be
// registered and selected per use.
library.add(faHouse, faHouseDuotone);
// <FontAwesomeIcon icon={['fad', 'house']} /> duotone
// <FontAwesomeIcon icon={['fas', 'house']} /> solid
// Practical advice: do not upgrade a plan for a handful of icons. Define the
// missing ones as custom definitions and keep the free package. Upgrade when
// the design system genuinely depends on the duotone style across hundreds
// of icons.One licensing point that catches teams out: the Pro icon sets are licensed per developer seat, and the terms restrict redistribution of the raw icon files. Self-hosting inside your own application's build is permitted; publishing the font files as a public asset or bundling them into an open-source template is not. Check the current terms before shipping.
FAQ
How do I make a custom icon appear in both Solid and Duotone?
Define two IconDefinitions with the same
iconName and different prefixes — fas and fad — and register both. A duotone definition's path entry is an object with primary and secondary path strings rather than a single string.Why is my duotone icon only one colour?
Most often the secondary opacity is zero, or both custom properties were set to the same value. Another cause is using the web-font route without Pro, where duotone needs special handling — check that the element actually has the
fa-duotone class and the duotone family is loaded.Related
Transforms, layering, masking and lists Upgrading from Font Awesome 5 and 6 to 7
Last refreshed 2026-09-18.