Plugin.Maui.BootstrapTheme
0.1.0-preview.6
dotnet add package Plugin.Maui.BootstrapTheme --version 0.1.0-preview.6
NuGet\Install-Package Plugin.Maui.BootstrapTheme -Version 0.1.0-preview.6
<PackageReference Include="Plugin.Maui.BootstrapTheme" Version="0.1.0-preview.6" />
<PackageVersion Include="Plugin.Maui.BootstrapTheme" Version="0.1.0-preview.6" />
<PackageReference Include="Plugin.Maui.BootstrapTheme" />
paket add Plugin.Maui.BootstrapTheme --version 0.1.0-preview.6
#r "nuget: Plugin.Maui.BootstrapTheme, 0.1.0-preview.6"
#:package Plugin.Maui.BootstrapTheme@0.1.0-preview.6
#addin nuget:?package=Plugin.Maui.BootstrapTheme&version=0.1.0-preview.6&prerelease
#tool nuget:?package=Plugin.Maui.BootstrapTheme&version=0.1.0-preview.6&prerelease
MauiBootstrapTheme
Use any Bootstrap or Bootswatch CSS theme in your .NET MAUI app — no custom controls required.
Drop a Bootstrap CSS file into your project, call .UseBootstrapTheme(), and at build time the CSS is parsed into a native ResourceDictionary with styles for stock MAUI controls.
How It Works
- Build time — The
MauiBootstrapTheme.BuildMSBuild task reads your Bootstrap CSS files and generates C#ResourceDictionarysource files (.g.cs) via XAML Source Gen. - Runtime — The generated dictionaries are merged into
Application.Resources, providingStyleClass-based styles for all stock MAUI controls. - No wrappers — Your
Button,Entry,Label,Border, etc. remain standard MAUI controls. Styling is applied throughStyleClassandDynamicResource.
Quick Start
1. Install
dotnet add package Plugin.Maui.BootstrapTheme
2. Add a Bootstrap CSS file
Place any Bootstrap or Bootswatch CSS file in your project's Resources/Themes/ folder (e.g., Resources/Themes/bootstrap.min.css). Mark it as a BootstrapTheme item in your .csproj:
<ItemGroup>
<BootstrapTheme Include="Resources/Themes/bootstrap.min.css" />
<BootstrapTheme Include="Resources/Themes/darkly.min.css" />
</ItemGroup>
3. Register in MauiProgram.cs
using MauiBootstrapTheme.Extensions;
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseBootstrapTheme();
return builder.Build();
}
4. Apply a theme
using MauiBootstrapTheme.Theming;
// Apply by name (matches the CSS filename without extension)
BootstrapTheme.Apply("bootstrap"); // default Bootstrap
BootstrapTheme.Apply("darkly"); // Bootswatch Darkly
BootstrapTheme.Apply("vapor"); // Bootswatch Vapor
5. Use StyleClass in XAML
<Button Text="Primary" StyleClass="btn-primary" />
<Button Text="Outline" StyleClass="btn-outline-danger" />
<Button Text="Large Pill" StyleClass="btn-success,btn-pill-lg" />
<Label Text="Page Title" StyleClass="h1" />
<Label Text="Section heading" StyleClass="h4" />
<Label Text="Helper text" StyleClass="text-muted" />
<Border StyleClass="card,shadow">
<VerticalStackLayout>
<Label Text="Card Title" StyleClass="h5" />
<Label Text="Card content here" />
</VerticalStackLayout>
</Border>
<Border StyleClass="text-bg-primary">
<Label Text="Primary background" StyleClass="on-primary" />
</Border>
<ProgressBar Progress="0.75" />
<ProgressBar Progress="0.5" StyleClass="progress-success" />
<Border StyleClass="badge,bg-danger">
<Label Text="Alert" StyleClass="on-danger" />
</Border>
Available Style Classes
Buttons
| StyleClass | Description |
|---|---|
btn-primary .. btn-dark |
Solid button variants (8 colors) |
btn-outline-primary .. btn-outline-dark |
Outline button variants |
btn-lg |
Large button sizing |
btn-sm |
Small button sizing |
btn-pill |
Pill-shaped (fully rounded) — default size |
btn-pill-lg |
Pill-shaped large button |
btn-pill-sm |
Pill-shaped small button |
Typography (Label)
| StyleClass | Description |
|---|---|
h1 .. h6 |
Heading levels with font size and weight |
text-muted |
Secondary/muted text color |
on-primary .. on-dark |
Contrast text color for use on colored backgrounds |
Cards & Containers (Border)
| StyleClass | Description |
|---|---|
card |
Card styling with border, corner radius, and padding |
shadow-sm |
Small shadow |
shadow |
Default shadow |
shadow-lg |
Large shadow |
text-bg-primary .. text-bg-dark |
Colored background containers |
bg-primary .. bg-warning |
Background color only |
badge |
Badge styling (small rounded container) |
Progress (ProgressBar)
| StyleClass | Description |
|---|---|
| (implicit) | Default primary progress color |
progress-primary |
Primary progress color |
progress-success |
Success progress color |
progress-danger |
Danger progress color |
DynamicResource Keys
All theme values are available as DynamicResource keys for use in XAML bindings:
Colors
Primary, Secondary, Success, Danger, Warning, Info, Light, Dark
Spacing & Sizing
CornerRadius, CornerRadiusSm, CornerRadiusLg, BorderWidth, ButtonHeight, ButtonHeightSm, ButtonHeightLg
Backgrounds
BodyBackground, SurfaceColor, Gray100
Typography
BodyFontSize, FontSizeH1 .. FontSizeH6
<Border Stroke="{DynamicResource Primary}" StyleClass="card">
<Label Text="Custom border color" />
</Border>
<CheckBox Color="{DynamicResource Primary}" />
<Switch OnColor="{DynamicResource Success}" />
<Slider MinimumTrackColor="{DynamicResource Primary}" ThumbColor="{DynamicResource Primary}" />
<ActivityIndicator Color="{DynamicResource Danger}" IsRunning="True" />
Dark Mode
Themes automatically support light/dark mode. The generated ResourceDictionary responds to system theme changes.
// Test dark mode programmatically
App.Current.UserAppTheme = AppTheme.Dark;
// Reset to system default
App.Current.UserAppTheme = AppTheme.Unspecified;
Handling Theme Changes
BootstrapTheme.Apply() swaps the merged ResourceDictionary and fires BootstrapTheme.ThemeChanged. Controls using DynamicResource bindings update automatically, but page backgrounds and any values read directly from BootstrapTheme.Current do not — pages must subscribe to the event and refresh.
XAML Pages
public partial class MyPage : ContentPage
{
public MyPage()
{
InitializeComponent();
this.BackgroundColor = BootstrapTheme.Current.GetBackground();
}
protected override void OnAppearing()
{
base.OnAppearing();
BootstrapTheme.ThemeChanged += OnThemeChanged;
}
protected override void OnDisappearing()
{
BootstrapTheme.ThemeChanged -= OnThemeChanged;
base.OnDisappearing();
}
private void OnThemeChanged(object? sender, EventArgs e)
{
this.BackgroundColor = BootstrapTheme.Current.GetBackground();
}
}
MauiReactor Pages
For MauiReactor projects, enable Reactor code generation in your .csproj:
<PropertyGroup>
<BootstrapThemeGenerateReactor>true</BootstrapThemeGenerateReactor>
</PropertyGroup>
This generates a Bs constants class and *ReactorTheme classes at build time.
Using Bs Constants
Use Bs.* constants instead of raw strings for IntelliSense and type safety:
// Typography — use .Class() consistently
Label("Dashboard").Class(Bs.H1)
Label("Description").Class(Bs.Lead)
// Buttons — use .Class() for composable styling
Button("Save").Class(Bs.BtnPrimary)
Button("Delete").Class(Bs.BtnDanger).Class(Bs.BtnSm)
Button("Submit").Class(Bs.BtnSuccess).Class(Bs.BtnLg)
// Forms
Entry().Placeholder("Email").Class(Bs.FormControl)
Picker().Class(Bs.FormSelect)
// Cards & containers
Border(content).Class(Bs.Card).Class(Bs.Shadow)
// Spacing constants (Bootstrap scale → dp)
VStack(spacing: Bs.Spacing3, ...) // 16dp
.Padding(Bs.Spacing4) // 24dp
// Bootstrap spacing utility helpers (no direct .Set(...))
Border(label).BsPadding0()
Border(label).BsPadding3()
Border(label).BsMargin2()
Theme Change Handling
Create a BasePage component that subscribes to ThemeChanged and calls Invalidate() to re-render:
abstract class BasePage : Component
{
protected override void OnMounted()
{
BootstrapTheme.ThemeChanged += OnThemeChanged;
base.OnMounted();
}
protected override void OnWillUnmount()
{
BootstrapTheme.ThemeChanged -= OnThemeChanged;
base.OnWillUnmount();
}
private void OnThemeChanged(object? sender, EventArgs e) => Invalidate();
public abstract VisualNode RenderContent();
public override VisualNode Render()
=> ContentPage(RenderContent())
.BackgroundColor(BootstrapTheme.Current.GetBackground());
}
Then every page extends BasePage and only implements RenderContent().
Included Sample Themes
The sample app ships with these Bootswatch themes:
| Theme | Description |
|---|---|
| Default | Standard Bootstrap 5 |
| Darkly | Dark theme with muted blue tones |
| Slate | Dark gunmetal-gray theme |
| Flatly | Flat and modern light theme |
| Sketchy | Hand-drawn style (requires Neucha font) |
| Vapor | Cyberpunk neon with dark background |
| Brite | Vibrant neon-inspired light theme |
To use any Bootswatch theme, download the CSS from bootswatch.com and add it to your project.
Font Handling
Some Bootstrap themes require specific fonts (e.g., Lato, Neucha). If a theme references a non-system font, the build emits a BT0001 warning with the exact code to add:
warning BT0001: Theme 'darkly' requires font 'Lato' which is not available as a system font.
Download the font file and add it to your project:
// In MauiProgram.cs, add to ConfigureFonts:
.ConfigureFonts(fonts =>
{
fonts.AddFont("lato.ttf", "Lato");
})
Known Limitations
- No text-shadow — MAUI does not support text shadow on
Label - No gradient backgrounds on buttons — CSS
background-image: linear-gradient(...)is parsed but MAUIButtondoes not supportLinearGradientBrushon all platforms; solidBackgroundcolor is used instead - No border-image — CSS decorative borders (e.g., Sketchy theme hand-drawn borders) cannot be replicated with native controls
- Shadow via StyleClass —
StyleClass="card,shadow"may not render on some platforms due to MAUI framework limitations withShadowin Style Setters; use thetheme:Bootstrap.Shadowattached property as a fallback - Font weight granularity — MAUI only supports
Boldand normal; CSSfont-weight: 500is mapped to normal - CornerRadius is integer —
Button.CornerRadiusisintin MAUI, so fractional CSS values are rounded - Percentage-based sizing — CSS percentage values (e.g.,
width: 50%) have no MAUI equivalent - No CSS custom properties at runtime — CSS variables are resolved at build time, not runtime
- Platform rendering differences — Some visual details (checkbox style, switch track shape) vary by platform
Attached Properties (Legacy)
The library also includes attached properties for scenarios where StyleClass is not sufficient:
xmlns:theme="clr-namespace:MauiBootstrapTheme.Theming;assembly=MauiBootstrapTheme"
<Border theme:Bootstrap.Shadow="Default" StyleClass="card">
<Label Text="Card with shadow" />
</Border>
Requirements
- .NET 10.0+
- MAUI workload installed
Building from Source
# Build the MSBuild task
dotnet build src/MauiBootstrapTheme.Build
# Build and run the sample app (macOS)
dotnet build samples/MauiBootstrapTheme.Sample -f net10.0-maccatalyst -t:Run
# Run tests
dotnet test tests/MauiBootstrapTheme.Build.Tests
Contributing
Contributions welcome! Please open an issue first to discuss what you'd like to change.
License
MIT License — see LICENSE for details.
Acknowledgments
- Bootswatch for the free Bootstrap themes
- Bootstrap for the CSS framework
- Inspired by FlagstoneUI
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-android36.0 is compatible. net10.0-ios26.0 is compatible. net10.0-maccatalyst26.0 is compatible. |
-
net10.0-android36.0
- Microsoft.Maui.Controls (>= 10.0.10)
-
net10.0-ios26.0
- Microsoft.Maui.Controls (>= 10.0.10)
-
net10.0-maccatalyst26.0
- Microsoft.Maui.Controls (>= 10.0.10)
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 |
|---|---|---|
| 0.1.0-preview.6 | 54 | 2/22/2026 |
| 0.1.0-preview.5 | 51 | 2/16/2026 |