Plugin.VariableFont
1.0.4
dotnet add package Plugin.VariableFont --version 1.0.4
NuGet\Install-Package Plugin.VariableFont -Version 1.0.4
<PackageReference Include="Plugin.VariableFont" Version="1.0.4" />
<PackageVersion Include="Plugin.VariableFont" Version="1.0.4" />
<PackageReference Include="Plugin.VariableFont" />
paket add Plugin.VariableFont --version 1.0.4
#r "nuget: Plugin.VariableFont, 1.0.4"
#:package Plugin.VariableFont@1.0.4
#addin nuget:?package=Plugin.VariableFont&version=1.0.4
#tool nuget:?package=Plugin.VariableFont&version=1.0.4
Plugin.VariableFont
A .NET MAUI plugin that brings variable font support to your app. Set any OpenType variation axis — weight, width, roundness, optical size, and dozens more — directly from XAML or C# on any supported control, on iOS, macOS, Android and Windows.
Installation
dotnet add package Plugin.VariableFont
Setup
Call .UseVariableFont() in your MauiProgram.cs:
builder
.UseMauiApp<App>()
.UseVariableFont()
.ConfigureFonts(fonts =>
{
fonts.AddFont("GoogleSansFlex.ttf", "GoogleSansFlex");
fonts.AddFont("Fraunces.ttf", "Fraunces");
});
Note: Nothing is altered at runtime unless
.UseVariableFont()is called. You can safely reference thevf:namespace in XAML without the plugin being active.
Usage
Add the namespace to your XAML file:
xmlns:vf="clr-namespace:Plugin.VariableFont;assembly=Plugin.VariableFont"
Then apply variation axes to any supported control:
<Label Text="Hello, World!"
FontFamily="GoogleSansFlex"
FontSize="48"
vf:VariableFont.Weight="900"
vf:VariableFont.Width="25"
vf:VariableFont.Roundness="100" />
Override font family and size independently from the standard MAUI properties:
<Entry vf:VariableFont.FontFamily="Fraunces"
vf:VariableFont.FontSize="32"
vf:VariableFont.Weight="100" />
Apply variations to individual Span elements inside a FormattedString:
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Light " vf:VariableFont.FontFamily="Fraunces" vf:VariableFont.Weight="100" />
<Span Text="Bold" vf:VariableFont.FontFamily="Fraunces" vf:VariableFont.Weight="900" />
</FormattedString>
</Label.FormattedText>
</Label>
Customize the Shell navigation bar title (iOS, macCatalyst and Android only):
<Shell vf:VariableFont.FontFamily="GoogleSansFlex"
vf:VariableFont.FontSize="20"
vf:VariableFont.Weight="700">
...
</Shell>
Note:
Shellis not supported on Windows. See Platform Support for details.
Platform Support
Controls
| Control | iOS | macCatalyst | Android (API 26+) | Windows |
|---|---|---|---|---|
Label |
✅ | ✅ | ✅ | ✅ |
Span (inside Label) |
✅ | ✅ | ✅ | ✅ |
Entry |
✅ | ✅ | ✅ | ✅ |
Editor |
✅ | ✅ | ✅ | ✅ |
Button |
✅ | ✅ | ✅ | ✅ |
RadioButton |
✅ | ✅ | ✅ | ✅ |
SearchBar |
✅ | ✅ | ✅ | ✅ |
Picker |
✅ | ✅ | ✅ | ✅ |
DatePicker |
✅ | ⚠️ | ✅ | ✅ |
TimePicker |
✅ | ⚠️ | ✅ | ✅ |
Shell (nav bar title) |
✅ | ✅ | ✅ | ❌ |
FontImageSource |
✅ | ✅ | ✅ | ⚠️ |
⚠️ macCatalyst — DatePicker / TimePicker: The
UIDatePickerandUITimePickercontrols on macCatalyst use a fixed-width internal column layout. There is no public.FontAPI and subview traversal breaks the layout. Custom fonts are not applied on this platform; a one-time warning is emitted to the debug output.
Android: Variable font support requires API level 26 (Android 8.0 Oreo) or higher. On lower API levels the plugin no-ops silently.
Windows: WinUI 3 renders text through DirectWrite, which interpolates a variable font only along the standard
wght(Weight),wdth(Width),ital(Italic) andslnt(Slant) axes — plus theFontFamily/FontSizeoverrides. All other custom axes (Grade, Roundness, Monospace, …) cannot be set through the WinUI text stack and are ignored, with a one-time warning emitted per axis to the debug output.Shellis not supported on Windows — the WinUI 3NavigationViewrenders its chrome through a control template that explicitly sets its own font properties, with no public API to override them reliably; a one-time warning is emitted.FontImageSourceis not supported on Windows (WinUI rasterizes glyphs through its own pipeline, which exposes no font-axis hook); a one-time warning is emitted.
Available Axes
The plugin exposes all registered OpenType variation axes as attached properties. Each axis is validated at the BindableProperty level — an ArgumentOutOfRangeException is thrown immediately if a value is out of range, making misconfiguration easy to catch during development.
| Property | Tag | Default | Range | Step |
|---|---|---|---|---|
Weight |
wght |
400 | 1 – 1000 | 1 |
Width |
wdth |
100 | 25 – 200 | 0.1 |
Italic |
ital |
— | 0 / 1 | — |
Slant |
slnt |
0 | -90 – 90 | 1 |
OpticalSize |
opsz |
14 | 5 – 1200 | 0.1 |
Grade |
GRAD |
0 | -1000 – 1000 | 1 |
Roundness |
ROND |
0 | 0 – 100 | 1 |
Casual |
CASL |
0 | 0 – 1 | 0.01 |
Cursive |
CRSV |
0.5 | 0 – 1 | 0.1 |
Softness |
SOFT |
0 | 0 – 100 | 0.1 |
Sharpness |
SHRP |
0 | 0 – 100 | 1 |
Flare |
FLRE |
0 | 0 – 100 | 1 |
Wonky |
WONK |
— | 0 / 1 | — |
Year |
YEAR |
2000 | -4000 – 4000 | 1 |
Morph |
MORF |
0 | 0 – 60 | 1 |
Informality |
INFM |
0 | 0 – 100 | 1 |
Monospace |
MONO |
0 | 0 – 1 | 0.01 |
Spacing |
SPAC |
0 | -100 – 100 | 0.1 |
Contrast |
CONT |
0 | -100 – 100 | 1 |
Bounce |
BNCE |
0 | -100 – 100 | 1 |
Fill |
FILL |
— | 0 / 1 | — |
Bleed |
BLED |
0 | 0 – 100 | 1 |
Scanlines |
SCAN |
0 | -100 – 100 | 1 |
Volume |
VOLM |
0 | 0 – 100 | 1 |
ElementShape |
ELSH |
0 | 0 – 100 | 0.1 |
ElementExpansion |
ELXP |
0 | 0 – 100 | 1 |
ElementGrid |
ELGR |
1 | 1 – 2 | 0.1 |
HyperExpansion |
HEXP |
0 | 0 – 100 | 0.1 |
VerticalExtension |
VEXT |
0 | 0 – 100 | 1 |
AscenderHeight |
ASCD |
750 | 0 – 1000 | 1 |
DescenderDepth |
DSCD |
-250 | -1000 – 0 | 1 |
LowercaseHeight |
LCSZ |
500 | 0 – 1000 | 1 |
UppercaseHeight |
UCSZ |
725 | 0 – 1000 | 1 |
FigureHeight |
FGSZ |
600 | -1000 – 2000 | 1 |
ThickStroke |
XTRA |
88 | -1000 – 2000 | 1 |
ThinStroke |
YTRA |
116 | -1000 – 2000 | 1 |
CounterWidth |
XOPQ |
400 | -1000 – 2000 | 1 |
ShadowLength |
SHDL |
50 | 0 – 100 | 0.1 |
EdgeHighlight ⚠️ |
EDHL |
12 | 0 – 1000 | 1 |
ExtrusionDepth ⚠️ |
EXTD |
100 | 0 – 1000 | 1 |
HorizontalElementAlignment |
HELA |
0 | -100 – 100 | 1 |
VerticalElementAlignment |
VELA |
0 | -100 – 100 | 1 |
RotationInX |
ROTX |
0 | -180 – 180 | 1 |
RotationInY |
ROTY |
0 | -180 – 180 | 1 |
RotationInZ |
ROTZ |
0 | -180 – 180 | 1 |
ARRetinalResolution |
ARRR |
10 | 10 – 60 | 1 |
SizeOfPaint1 |
sze1 |
0 | -100 – 100 | 1 |
SizeOfPaint2 |
sze2 |
0 | -100 – 100 | 1 |
HorizontalPositionOfPaint1 |
pos1 |
0 | -100 – 100 | 1 |
HorizontalPositionOfPaint2 |
pos2 |
0 | -100 – 100 | 1 |
VerticalPositionOfPaint1 |
vps1 |
0 | -100 – 100 | 1 |
VerticalPositionOfPaint2 |
vps2 |
0 | -100 – 100 | 1 |
⚠️
EdgeHighlight: Does not function as expected on iOS and macCatalyst due to platform rendering limitations. ⚠️ExtrusionDepth: Does not function as expected on iOS and macCatalyst due to platform rendering limitations.
Not all axes are available in all fonts. The plugin passes only the axes that the font actually supports — unsupported axes are silently ignored at the platform level.
FontImageSource
Variable font icons work on ImageButton, Image, and Button (as icon):
<ImageButton>
<ImageButton.Source>
<FontImageSource FontFamily="MaterialSymbols"
Glyph=""
Size="48"
Color="White"
vf:VariableFont.Weight="700"
vf:VariableFont.Fill="True" />
</ImageButton.Source>
</ImageButton>
Requirements
- .NET 8.0, 9.0 or 10.0 MAUI
- iOS 16.0+
- macCatalyst 16.0+
- Android API 26+ (Android 8.0 Oreo) for variable font rendering
- Windows 10 build 19041+ (Windows App SDK / WinUI 3) — Weight, Width, Italic, Slant only
License
Free to use in personal and commercial projects. Source code is not provided. See the LICENSE file for full terms.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-android is compatible. net8.0-ios is compatible. net8.0-maccatalyst is compatible. net8.0-windows10.0.19041 is compatible. net9.0-android was computed. net9.0-android35.0 is compatible. net9.0-ios was computed. net9.0-ios18.0 is compatible. net9.0-maccatalyst was computed. net9.0-maccatalyst18.0 is compatible. net9.0-windows was computed. net10.0-android was computed. net10.0-android36.0 is compatible. net10.0-ios was computed. net10.0-ios26.0 is compatible. net10.0-maccatalyst was computed. net10.0-maccatalyst26.0 is compatible. net10.0-windows was computed. |
-
net10.0-android36.0
- Microsoft.Maui.Controls (>= 10.0.0)
-
net10.0-ios26.0
- Microsoft.Maui.Controls (>= 10.0.0)
-
net10.0-maccatalyst26.0
- Microsoft.Maui.Controls (>= 10.0.0)
-
net8.0-android
- Microsoft.Maui.Controls (>= 8.0.0)
-
net8.0-ios
- Microsoft.Maui.Controls (>= 8.0.0)
-
net8.0-maccatalyst
- Microsoft.Maui.Controls (>= 8.0.0)
-
net8.0-windows10.0.19041
- Microsoft.Maui.Controls (>= 8.0.0)
-
net9.0-android35.0
- Microsoft.Maui.Controls (>= 9.0.0)
-
net9.0-ios18.0
- Microsoft.Maui.Controls (>= 9.0.0)
-
net9.0-maccatalyst18.0
- Microsoft.Maui.Controls (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.4 | 94 | 5/18/2026 |