Architecture
Understand the internal architecture of MonorailCSS
MonorailCSS is built with a modular architecture designed for extensibility and performance.
Core Components
1. CssFramework
The main entry point that orchestrates the entire processing pipeline. It handles parsing, compilation, post-processing, and CSS generation.
2. Utilities System
Self-contained components that compile CSS class candidates into AST nodes. Each utility handles specific CSS properties:
- Static utilities extend
BaseStaticUtilityfor fixed property/value mappings - Functional utilities extend
BaseFunctionalUtilityfor theme-aware dynamic values - Specialized base classes exist for common patterns (colors, spacing, filters)
3. Candidate System
Represents parsed utility classes with variants and modifiers. The CandidateParser tokenizes and structures raw class names.
4. AST (Abstract Syntax Tree)
Intermediate representation of CSS rules before final generation. Node types include:
- Declaration - CSS property-value pairs with optional importance flag
- StyleRule - CSS rules with selectors and nested declarations
- NestedRule - Nested rules using parent selector (
&) syntax - AtRule - At-rules like
@media,@supports,@layer - ComponentRule - Component-level style rules
- Comment - CSS comments
- Context - Container for nodes with associated metadata
- RawCss - Raw CSS content pass-through
5. Processing Pipeline
Multi-stage transformation pipeline that processes AST nodes through the following stages (in order):
- Theme variable tracking - Tracks which theme variables are used for optimization
- Arbitrary value validation - Validates user-defined arbitrary values in square brackets
- Negative value normalization - Handles negative value prefixes (e.g.,
-m-4) - Color modifier processing - Applies color opacity and mixing modifiers
- Important flag handling - Processes
!important modifiers - Variable fallback resolution - Resolves CSS variable fallback values
- Property registration - Registers CSS custom properties for tracking
- Processing and sorting - Applies variants and sorts rules for proper CSS output order
- Declaration merging - Combines duplicate declarations within rules
- Media query consolidation - Groups rules by media queries
- Layer assignment - Assigns CSS cascade layers (base, components, utilities)
6. Theme System
Manages design tokens and CSS custom properties. Supports theme customization and usage tracking for optimization.
7. Variant System
Handles pseudo-classes, media queries, and other CSS modifiers. Built-in variants are automatically registered.
8. Apply/Component System
Processes @apply directives for creating reusable component classes. The ApplyProcessor expands utility classes into CSS declarations for custom selectors.
Key features:
- Dedicated processing pipeline for apply rules
- Supports variants within component classes (e.g.,
hover:bg-blue-500in applies) - Handles selector transformation for component styles
- Merges declarations and properly wraps with media queries/at-rules
9. Support Components
Additional components that support core functionality:
- CssPropertyRegistry - Tracks and manages CSS custom properties used throughout the generated stylesheet
- ThemeUsageTracker - Monitors which theme variables are referenced, enabling tree-shaking of unused theme values for optimization
- PostProcessor - Handles variant application and wraps rules with appropriate selectors and at-rules
- SortingManager - Ensures proper CSS output ordering based on utility priorities and variant weights
- DeclarationMerger - Combines duplicate CSS declarations within rules to minimize output size
Extensibility
Runtime Customization
The framework supports adding custom utilities and variants at runtime:
- AddUtility(IUtility) - Register a single custom utility implementation
- AddUtilities(IEnumerable
) - Register multiple custom utilities at once - AddVariant(IVariant, bool) - Register custom variants with optional overwrite of built-in variants
- CustomUtilityFactory - Creates utilities from configuration settings
This allows for framework extension without modifying core code. Custom utilities/variants can be added through settings or programmatically.
Additional Features
Preflight CSS
Optional CSS reset/normalize generation via the IncludePreflight setting. When enabled, the framework generates Tailwind-compatible preflight styles that provide consistent cross-browser defaults.
Font Variable Handling
Special handling for font family variables to maintain Tailwind v4 compatibility:
- Automatic inclusion of
--font-sansand--font-monovariables - Default fallback values for common font stacks
--default-font-familyand--default-mono-font-familyderived variables
Layer System
Utilities are assigned to CSS cascade layers for proper specificity control:
- base - Reset and base styles (preflight)
- components - Component classes from
@applydirectives - utilities - Utility classes
This ensures utilities can always override components, and components can override base styles.
Key Design Patterns
- Auto-Discovery: Utilities are automatically discovered via reflection at startup
- Priority System: Utilities have priorities (0-1000) determining evaluation order
- Immutable Data: Extensive use of immutable collections
- Pipeline Architecture: Modular stages for processing transformations
- Theme Resolution: Values resolved through namespace chains with fallback support
- Arbitrary Values: Support for user-defined values in square brackets
[value]
Testing Strategy
The project uses integration testing rather than unit testing individual utilities. The main test file tests/MonorailCss.Tests/Interactive/AllUtilitiesIntegrationTest.cs verifies that utilities generate expected CSS properties.
When adding new utilities:
- Create the utility class in appropriate category folder
- Add test cases to
AllUtilitiesIntegrationTest.cs - Verify all tests pass before committing