Easily Use Icon Fonts in .NET MAUI with IconFont.Maui

If you’ve ever used icon fonts in a .NET MAUI app, you know the drill: find the Unicode codepoint for the icon you need, copy-paste a cryptic string like "\uF4DA" into your XAML, forget what it means two days later, and repeat. Not great for maintainability. And that’s if you even get the font registered correctly in the first place!
I wanted to make this better. So I built IconFont.Maui — a set of packages and a template repository that give you strongly-typed, IntelliSense-friendly glyph constants generated directly from your TTF files at compile time. No manual mapping, no copy-pasting Unicode values.
The Problem #
Using icon fonts in .NET MAUI typically means something like this:
<Label Text=""
FontFamily="BootstrapIcons" />
What icon is that? Good luck remembering. And if the font updates and codepoints shift? You’re in for a fun afternoon of fixing things.
What I wanted was something like this:
<Label Text="{x:Static icons:BootstrapIcons.Search}"
FontFamily="{x:Static icons:BootstrapIcons.FontFamily}" />
Clear, discoverable, and if the font updates you just drop in the new TTF and rebuild. The source generator takes care of the rest.
How It Works #
At the core is IconFont.Maui.SourceGenerator, a Roslyn source generator that reads your TTF file’s OpenType tables (cmap and post) at compile time and emits a C# class with const string fields for every glyph. It also generates builder extension methods, font registration, and a FontFamily constant per class.
The key thing: this is a build-time only dependency. The source generator runs during compilation and the resulting NuGet package for your icon font has zero runtime dependency on it.
Here’s what the ecosystem looks like:
| Package | Purpose |
|---|---|
IconFont.Maui.SourceGenerator | The shared source generator. Reference this to generate glyph constants from any TTF. |
IconFont.Maui.Template | Template repo — clone it, drop in your TTF, ship your own icon font package. |
IconFont.Maui.FluentIcons | Ready-to-use package for Fluent UI System Icons. |
Using an Existing Package #
If you just want to use Fluent Icons in your app, install the NuGet package:
dotnet add package IconFont.Maui.FluentIcons
Register the fonts in your MauiProgram.cs:
var builder = MauiApp.CreateBuilder()
.UseMauiApp<App>()
.UseIconFonts(); // registers all Fluent Icon font variations
Then use the icons in XAML:
xmlns:icons="clr-namespace:IconFont.Maui.FluentIcons;assembly=IconFont.Maui.FluentIcons"
<Image WidthRequest="24" HeightRequest="24">
<Image.Source>
<FontImageSource Glyph="{x:Static icons:FluentIconsRegular.Home24}"
FontFamily="{x:Static icons:FluentIconsRegular.FontFamily}"
Size="24" />
</Image.Source>
</Image>
Or in C#:
var icon = new FontImageSource
{
Glyph = FluentIconsFilled.Heart24,
FontFamily = FluentIconsFilled.FontFamily,
Size = 24,
Color = Colors.Red
};
Each font variation gets its own class (FluentIconsRegular, FluentIconsFilled, FluentIconsLight, etc.) with its own FontFamily constant. No nested classes, no awkward XAML syntax — just ClassName.IconName.
Creating Your Own Icon Font Package #
This is where it gets fun. Want to ship your own icon font as a NuGet package? Clone the template:
git clone https://github.com/jfversluis/IconFont.Maui.Template.git MyAwesomeIcons
The template comes with everything pre-wired:
- Drop in your TTF — replace the sample font files in
Resources/Fonts/ - Configure
IconFont.props— tell the generator about your font:
<ItemGroup>
<IconFontDefinition Include="Resources/Fonts/my-icons.ttf">
<FontAlias>MyIcons</FontAlias>
<FontClass>MyIcons</FontClass>
<FontNamespace>MyCompany.Icons</FontNamespace>
</IconFontDefinition>
</ItemGroup>
- Build — the source generator parses the TTF and emits all the glyph constants
- Ship it — the template includes CI/CD workflows for publishing to NuGet
That’s it. You now have a NuGet package with strongly-typed glyph constants, builder extensions, and automatic font registration. Your consumers just install the package, call .UseIconFonts(), and start using {x:Static} references in their XAML. They never need to know about the source generator — it’s not a runtime dependency of the resulting package.
Multi-Style Fonts #
Some icon fonts ship multiple styles. Fluent Icons, for example, has Regular, Filled, Light, and Resizable variations — each in their own TTF file. The source generator handles this by creating a separate class per font file:
FluentIconsRegular.Home24/FluentIconsRegular.FontFamilyFluentIconsFilled.Home24/FluentIconsFilled.FontFamilyFluentIconsLight.Home24/FluentIconsLight.FontFamily
If your TTF contains mixed styles (like glyphs with both _regular and _filled suffixes), the generator splits them into separate classes automatically. Pretty neat.
How It Differs from Manual Approaches #
You might be thinking: “Can’t I just write a script to parse the font and generate a C# file?” Sure, you can. But here’s why the source generator approach is better:
- Always in sync: The constants are generated from the TTF at every build. Update the font, rebuild, done.
- No checked-in generated code: The glyph constants aren’t in your source tree. They’re generated in the
obj/folder during compilation. - Shared infrastructure: Every icon font package uses the same source generator. No code duplication across repos.
const stringvalues: These work with{x:Static}in XAML, which requires compile-time constants. Astatic readonlyfield won’t cut it.
What’s Next #
I have a couple of improvements planned:
- Convention over configuration (#1): Make
IconFont.propsoptional for simple scenarios by automatically deriving font metadata fromMauiFontitems. This would reduce setup to literally two lines in your csproj. - Missing initializer warning (#2): A Roslyn analyzer that warns you at compile time if you reference icon glyphs but forgot to call
.UseIconFonts()on yourMauiAppBuilder.
Get Started #
Everything is open source and available now:
- 📦 IconFont.Maui.SourceGenerator on NuGet
- 📦 IconFont.Maui.FluentIcons on NuGet
- 🧩 Template repo on GitHub
If you have a favorite icon font that you’d like to see as a package, clone the template and give it a shot. I’d love to see what you build with it!