[
](https://dotnet.
microsoft.com/)
Server-rendered UI components for ASP.NET Core with first-class htmx integration.
htmxRazor is a complete UI component library implemented as Razor Tag Helpers. Every component renders clean, semantic HTML styled by its own CSS design system. No client-side framework required — just add htmx attributes to any component for dynamic behavior.
- Server-rendered — No JavaScript framework. Components are Tag Helpers that render HTML on the server.
- htmx-native — Every component supports
hx-get,hx-post,hx-target,hx-swap, and all htmx attributes directly. - 72 components — Buttons, forms, dialogs, tabs, trees, carousels, data visualization, and more across 10 categories.
- Design tokens — Light/dark themes via CSS custom properties. Toggle with
data-rhx-themeorRHX.toggleTheme(). - Accessible — Semantic HTML, ARIA attributes, keyboard navigation, and screen reader support built in.
- Model binding — Form components integrate with ASP.NET Core model binding, validation, and
ModelExpression. - Zero config — One NuGet package. Two lines of setup. Start using components immediately.
dotnet add package htmxRazor// Program.cs
builder.Services.AddRazorPages();
builder.Services.AddhtmxRazor();
var app = builder.Build();
app.UseStaticFiles();
app.UsehtmxRazor(); // Serves component CSS, JS, and htmx from /_rhx/
app.MapRazorPages();
app.Run();@* _ViewImports.cshtml *@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, htmxRazor<rhx-button rhx-variant="brand" rhx-size="large">
Save Changes
</rhx-button><rhx-button rhx-variant="brand">Brand</rhx-button>
<rhx-button rhx-variant="success" rhx-appearance="outlined">Success</rhx-button>
<rhx-button rhx-variant="danger" rhx-appearance="plain">Delete</rhx-button>
<rhx-button rhx-variant="brand" rhx-pill="true">Pill Shape</rhx-button>
<rhx-button rhx-variant="brand" rhx-loading="true">Saving...</rhx-button><!-- Auto-detects type, label, validation from model metadata -->
<rhx-input rhx-for="Email" rhx-with-clear="true" />
<rhx-input rhx-label="Password"
rhx-type="password"
rhx-password-toggle="true"
name="password" /><!-- Live search with debounce -->
<rhx-input rhx-label="Search"
rhx-placeholder="Type to search..."
hx-get="/search"
hx-trigger="input changed delay:300ms"
hx-target="#results" />
<!-- Delete with confirmation -->
<rhx-button rhx-variant="danger"
hx-delete="/api/items/42"
hx-confirm="Are you sure?"
hx-target="#item-list"
hx-swap="outerHTML">
Delete
</rhx-button><rhx-button rhx-variant="brand" data-rhx-dialog-open="edit-dialog">
Edit Profile
</rhx-button>
<rhx-dialog id="edit-dialog" rhx-label="Edit Profile">
<rhx-input rhx-for="DisplayName" />
<rhx-dialog-footer>
<rhx-button rhx-variant="neutral" rhx-appearance="outlined"
onclick="this.closest('dialog').close()">Cancel</rhx-button>
<rhx-button rhx-variant="brand" type="submit">Save</rhx-button>
</rhx-dialog-footer>
</rhx-dialog><!-- Set theme on <html> -->
<html data-rhx-theme="light">
<!-- Toggle programmatically -->
<rhx-button onclick="RHX.toggleTheme()">Toggle Theme</rhx-button>
<!-- Override any design token -->
<style>
:root {
--rhx-color-brand-500: #6366f1;
--rhx-radius-md: 0.75rem;
}
</style>| Category | Components |
|---|---|
| Actions | Button, Button Group, Dropdown |
| Forms | Input, Textarea, Select, Combobox, Checkbox, Switch, Radio, Slider, Rating, Color Picker, File Input, Number Input |
| Feedback | Callout, Badge, Tag, Spinner, Skeleton, Progress Bar, Progress Ring, Tooltip |
| Navigation | Tabs, Breadcrumb, Tree, Carousel |
| Organization | Card, Divider, Split Panel, Scroller |
| Overlays | Dialog, Drawer, Details |
| Imagery | Icon (43 built-in), Avatar, Animated Image, Comparison, Zoomable Frame |
| Formatting | Format Bytes, Format Date, Format Number, Relative Time |
| Utilities | Copy Button, QR Code, Animation, Popup, Popover |
| Patterns | Active Search, Infinite Scroll, Lazy Load, Poll |
| htmxRazor | Bootstrap | Blazor | Web Awesome | |
|---|---|---|---|---|
| Rendering | Server (Tag Helpers) | Client (jQuery/JS) | Client (WebAssembly/SignalR) | Client (Web Components) |
| htmx support | Native on every component | Manual attribute wiring | N/A (own reactivity) | Manual attribute wiring |
| Bundle size | CSS + htmx (~14 KB gzip) | ~24 KB JS + ~22 KB CSS | ~2 MB WebAssembly runtime | ~80 KB JS |
| Model binding | ASP.NET Core ModelExpression |
None | Blazor @bind |
None |
| Dependencies | ASP.NET Core | jQuery | .NET runtime in browser | Lit |
| Theming | CSS custom properties | Sass variables | CSS isolation | CSS custom properties |
| Project | Description |
|---|---|
htmxRazor |
Core Tag Helper library with embedded CSS/JS assets |
htmxRazor.Demo |
Documentation site showcasing all components |
htmxRazor.Tests |
1,436 unit tests for Tag Helper rendering |
# Build
dotnet build
# Run tests
dotnet test
# Run the demo site
dotnet run --project htmxRazor.Demo
# Pack for NuGet
dotnet pack htmxRazor/htmxRazor.csproj --configuration ReleasehtmxRazor owns its entire rendering and styling stack:
- CSS Custom Properties for design tokens (colors, spacing, typography, borders, shadows)
- BEM naming with
rhx-prefix (rhx-button,rhx-button--brand,rhx-button__label) - Light/dark themes via
data-rhx-themeattribute on<html> - Utility classes for layout and spacing (
rhx-flex,rhx-gap-md,rhx-p-lg) - Auto-injected assets —
AddhtmxRazor()injects tokens, reset, core, and utilities CSS plus the htmx script into<head>
The project uses a custom CSS design system — not Bootstrap or any other CSS framework.
Key details from the codebase instructions:
- BEM naming convention with an rhx- prefix (e.g., .rhx-button, .rhx-button--loading, .rhx-button__icon)
- CSS custom properties (design tokens) defined in rhx-tokens.css — things like --rhx-color-brand-500, --rhx-radius-md, --rhx-font-size-base
- Light/dark theme support via a data-rhx-theme attribute on
- Each component has its own scoped CSS file in Assets/css/components/
- All CSS is embedded and served at /_rhx/ — no external dependencies
- Hardcoded values are not allowed; everything references var(--rhx-*) tokens
It's a fully self-contained design system built specifically for this component library.
| Version | Scope |
|---|---|
| v0.1.0 | Button, Input, Validation — minimum viable library |
| v0.2.0 | All Form Controls + Feedback components |
| v0.3.0 | Navigation + Organization components |
| v0.4.0 | Imagery + Utilities + Data Visualization |
| v0.5.0 | Composite Patterns (infinite scroll, search, poll, lazy load) |
| v1.0.0 | Full catalog, stable API, comprehensive docs, theme system |
See CONTRIBUTING.md for development setup, PR guidelines, and coding standards.
MIT - Copyright (c) 2024 Chris Woody Woodruff