Flowery.NET provides two distinct sizing systems. Understanding when to use each is essential:
| System | Purpose | Scope |
|---|---|---|
Global Size (FlowerySizeManager) |
User preference / accessibility | Entire app – all controls respond |
Auto Scaling (FloweryScaleManager) |
Responsive window-based sizing | Per-container opt-in only |
> 💡 Most apps should just use Global Size. Auto Scaling is an advanced feature for specific responsive-layout scenarios like data forms.
The FlowerySizeManager is a static service that:
Apply a global size to all controls:
using Flowery.Controls;
// Apply a size by enum
FlowerySizeManager.ApplySize(DaisySize.Small);
// Or by name (case-insensitive)
FlowerySizeManager.ApplySize("Large");
| Size | Typical Use Case |
|---|---|
ExtraSmall |
High-density UIs, data tables, compact toolbars |
Small |
Default - Good balance for desktop apps |
Medium |
Touch-friendly, accessibility |
Large |
Larger screens, presentations |
ExtraLarge |
Maximum readability, kiosk mode |
// Get the current global size
DaisySize currentSize = FlowerySizeManager.CurrentSize;
// Check/set if new controls should auto-use global size
FlowerySizeManager.UseGlobalSizeByDefault = true;
// Apply a size by enum
FlowerySizeManager.ApplySize(DaisySize.Medium);
// Apply a size by name (returns true if successful)
bool success = FlowerySizeManager.ApplySize("ExtraLarge");
// Reset to default (Small)
FlowerySizeManager.Reset();
// Subscribe to size changes
FlowerySizeManager.SizeChanged += (sender, size) =>
{
Console.WriteLine($"Size changed to: {size}");
// Update your custom controls here
};
Flowery.NET provides ready-to-use controls for size selection:
A ComboBox-style dropdown that shows all available sizes with localized names:
<controls:DaisySizeDropdown />
The dropdown:
SizeOptions property.
All DaisyUI controls with a Size property respond to global size changes:
DaisyButtonDaisyInput / DaisyTextAreaDaisySelectDaisyCheckBox / DaisyRadio / DaisyToggleDaisyBadgeDaisyProgress / DaisyRadialProgressDaisyTabsDaisyMenuDaisyKbdDaisyAvatarDaisyLoadingDaisyFileInputDaisyNumericUpDownDaisyDateTimelineFor regular TextBlock elements that should scale with the global size, use the ResponsiveFont attached property:
<TextBlock Text="Description text"
controls:FlowerySizeManager.ResponsiveFont="Primary" />
| Tier | Description | XS/S/M/L/XL Font Sizes |
|---|---|---|
Primary |
Body text, descriptions | 10/12/14/18/20 |
Secondary |
Hints, captions, labels | 9/10/12/14/16 |
Tertiary |
Very small text, counters | 8/9/11/12/14 |
Header |
Section titles, headings | 14/16/20/24/28 |
<!-- Body text -->
<TextBlock Text="This is a description that scales with global size."
controls:FlowerySizeManager.ResponsiveFont="Primary" />
<!-- Hint/caption text -->
<TextBlock Text="Optional field" Opacity="0.7"
controls:FlowerySizeManager.ResponsiveFont="Secondary" />
<!-- Section header -->
<TextBlock Text="Settings" FontWeight="Bold"
controls:FlowerySizeManager.ResponsiveFont="Header" />
The attached property:
1. Subscribes the TextBlock to FlowerySizeManager.SizeChanged
2. Immediately applies the font size for the current global size
3. Updates automatically when the global size changes
4. Cleans up the subscription when the control is unloaded
> Note: DynamicResource bindings to dynamically updated resources don't propagate reliably in Avalonia due to nested resource dictionary scoping. The ResponsiveFont attached property is the recommended approach for text that should scale with global size.
To make your own controls respond to global size changes:
public class MyCustomControl : UserControl
{
public MyCustomControl()
{
InitializeComponent();
// Subscribe to global size changes
FlowerySizeManager.SizeChanged += OnSizeChanged;
// Apply initial size
ApplySize(FlowerySizeManager.CurrentSize);
}
protected override void OnUnloaded(RoutedEventArgs e)
{
base.OnUnloaded(e);
// Clean up subscription
FlowerySizeManager.SizeChanged -= OnSizeChanged;
}
private void OnSizeChanged(object? sender, DaisySize size)
{
ApplySize(size);
}
private void ApplySize(DaisySize size)
{
// Scale your control based on size
var fontSize = size switch
{
DaisySize.ExtraSmall => 10,
DaisySize.Small => 12,
DaisySize.Medium => 14,
DaisySize.Large => 16,
DaisySize.ExtraLarge => 18,
_ => 14
};
MyTextBlock.FontSize = fontSize;
}
}
For DaisyUI-style controls, add a Size styled property:
public class MyDaisyControl : TemplatedControl
{
public static readonly StyledProperty<DaisySize> SizeProperty =
AvaloniaProperty.Register<MyDaisyControl, DaisySize>(
nameof(Size), DaisySize.Small);
public DaisySize Size
{
get => GetValue(SizeProperty);
set => SetValue(SizeProperty, value);
}
}
Then use design tokens in your theme:
<Style Selector="local|MyDaisyControl[Size=Small]">
<Setter Property="FontSize" Value="{DynamicResource DaisySizeSmallFontSize}" />
<Setter Property="Height" Value="{DynamicResource DaisySizeSmallHeight}" />
</Style>
<Style Selector="local|MyDaisyControl[Size=Large]">
<Setter Property="FontSize" Value="{DynamicResource DaisySizeLargeFontSize}" />
<Setter Property="Height" Value="{DynamicResource DaisySizeLargeHeight}" />
</Style>
For host applications like the Gallery, you can automatically apply sizes to all DaisyUI controls in the visual tree:
private static void ApplyGlobalSizeToControls(Control root, DaisySize size)
{
foreach (var control in root.GetVisualDescendants().OfType<Control>())
{
var sizeProperty = control.GetType().GetProperty("Size");
if (sizeProperty != null &&
sizeProperty.PropertyType == typeof(DaisySize) &&
sizeProperty.CanWrite)
{
sizeProperty.SetValue(control, size);
}
}
}
Sometimes you have controls that should not respond to global size changes - for example, demonstration controls showing all five size variants. Use the IgnoreGlobalSize attached property:
<controls:DaisyButton controls:FlowerySizeManager.IgnoreGlobalSize="True"
Size="Large" Content="I stay Large!" />
Mark a parent container to protect all descendant controls:
<StackPanel controls:FlowerySizeManager.IgnoreGlobalSize="True">
<!-- All size example controls inside are protected -->
<controls:DaisyAvatar Size="ExtraSmall" />
<controls:DaisyAvatar Size="Small" />
<controls:DaisyAvatar Size="Medium" />
<controls:DaisyAvatar Size="Large" />
<controls:DaisyAvatar Size="ExtraLarge" />
</StackPanel>
The attached property is inherited through the visual tree, so you only need to set it on the outermost container.
Size names are fully localized. Add translations to your language files:
{
"Size_ExtraSmall": "Extra Small",
"Size_Small": "Small",
"Size_Medium": "Medium",
"Size_Large": "Large",
"Size_ExtraLarge": "Extra Large"
}
Supported languages: English, German, French, Spanish, Italian, Japanese, Korean, Arabic, Turkish, Ukrainian, Chinese (Simplified).
The sizing system works with Design Tokens. Each size tier maps to specific tokens:
| Size | Height Token | Font Size Token |
|---|---|---|
| ExtraSmall | DaisySizeExtraSmallHeight (24) |
DaisySizeExtraSmallFontSize (10) |
| Small | DaisySizeSmallHeight (32) |
DaisySizeSmallFontSize (12) |
| Medium | DaisySizeMediumHeight (48) |
DaisySizeMediumFontSize (14) |
| Large | DaisySizeLargeHeight (64) |
DaisySizeLargeFontSize (18) |
| ExtraLarge | DaisySizeExtraLargeHeight (80) |
DaisySizeExtraLargeFontSize (20) |
1. Start with Small - The default size of Small works well for most desktop applications.
2. Provide a size picker - Give users control over the size preference, especially for accessibility.
3. Test all sizes - Ensure your layouts don't break at ExtraSmall (compact) or ExtraLarge (spacious).
4. Use tokens, not hardcoded values - This ensures your custom controls scale properly.
5. Unsubscribe from events - Always clean up SizeChanged subscriptions in OnUnloaded to prevent memory leaks.
A complete example of a settings panel with size selection:
<StackPanel Spacing="16">
<TextBlock Text="Display Size" FontWeight="Bold" />
<controls:DaisySizeDropdown Width="180" />
<TextBlock Text="This text will resize when you change the size above."
FontSize="{DynamicResource DaisySizeMediumFontSize}" />
<controls:DaisyButton Content="Sample Button" />
<controls:DaisyInput Watermark="Sample Input" />
</StackPanel>
All controls in the panel will automatically resize when the dropdown selection changes.
While FlowerySizeManager provides discrete size tiers (Small, Medium, Large), Flowery.NET also offers continuous font scaling based on window size through FloweryScaleManager.
> ⚠️ Important: These are two separate, independent systems. Auto Scaling ONLY affects controls within a container marked with EnableScaling="True". It does NOT affect the rest of your app (sidebar, navigation, etc.).
| Feature | Global Size | Auto Scaling |
|---|---|---|
| Service | FlowerySizeManager |
FloweryScaleManager |
| Scope | Entire app (global) | Only containers with EnableScaling="True" |
| Scaling Type | Discrete tiers (xs, s, m, l, xl) | Continuous (0.5× to 1.0×) |
| Trigger | User selection via dropdown | Automatic based on window size |
| What Changes | Height, padding, font size | Font size and scaled properties only |
| Best For | User preference, accessibility | Responsive data forms, dashboards |
Auto Scaling is opt-in and scoped. Only controls inside a container with EnableScaling="True" are affected:
xmlns:services="clr-namespace:Flowery.Services;assembly=Flowery.NET"
<Window>
<!-- Sidebar: NOT affected by Auto Scaling (uses Global Size) -->
<controls:FloweryComponentSidebar />
<!-- Content area: ONLY this panel uses Auto Scaling -->
<UserControl services:FloweryScaleManager.EnableScaling="True">
<!-- These controls scale with window size -->
<controls:DaisyInput Label="Name" />
<controls:DaisyButton Content="Submit" />
</UserControl>
</Window>
1. Set EnableScaling="True" on a container (UserControl, Window, Panel, etc.)
2. The manager tracks the parent TopLevel size (desktop Window or browser root)
3. Calculates a scale factor:
- Downscaling: min(width/1920, height/1080)
- If MaxScaleFactor > 1.0, scale-up is allowed based on the available dimension
- Clamped to MinScaleFactor … MaxScaleFactor
4. ONLY child controls inside that container adjust their font sizes
5. Controls outside the EnableScaling region are NOT affected
By default, Auto Scaling only scales down (max is 1.0). On large 4K windows (especially at 100% Windows scaling) you may want the UI to scale up as well.
To allow scaling above 1.0, set FloweryScaleManager.MaxScaleFactor to your desired physical maximum (for example 1.5 to match 150% Windows scaling):
FloweryScaleManager.MaxScaleFactor = 1.5;
When MaxScaleFactor > 1.0, Flowery compensates for OS DPI scaling using TopLevel.RenderScaling, so you don't double-scale on systems already set to 125% / 150% Windows scaling.
MaxScaleFactor (and internal scale factors) are sanity-capped at 5.0 (500%) to prevent extreme values.
You can enable/disable Auto Scaling programmatically:
// Disable Auto Scaling globally (scale factor becomes 1.0)
FloweryScaleManager.IsEnabled = false;
// Re-enable
FloweryScaleManager.IsEnabled = true;
When IsEnabled = false, all scale factors reset to 1.0 (no scaling).
Controls implementing IScalableControl auto-scale when inside an enabled container:
DaisyInput / DaisyTextArea (label + text font)DaisyButton (content font)DaisySelect (font)DaisyBadge (content font)#### Pattern 1: Global Size Only (Most Apps)
Most desktop apps should just use Global Size:
<!-- In sidebar or settings -->
<controls:DaisySizeDropdown />
<!-- All controls across the app respond to the user's size preference -->
#### Pattern 2: Auto Scaling for a Specific Page
Use Auto Scaling for a data-dense page that benefits from window-responsive sizing:
<UserControl services:FloweryScaleManager.EnableScaling="True">
<!-- Customer details form that scales with window -->
<controls:DaisyCard Padding="{services:Scale SpacingMedium}">
<TextBlock FontSize="{services:Scale FontTitle}" Text="Customer" />
<controls:DaisyInput Label="Name" />
<controls:DaisyInput Label="Email" />
</controls:DaisyCard>
</UserControl>
#### Pattern 3: Override Auto Scaling with Global Size
If Auto Scaling is on, but you want specific controls to use the fixed Global Size instead, mark them to opt out:
<UserControl services:FloweryScaleManager.EnableScaling="True">
<!-- These scale with window -->
<controls:DaisyInput Label="Name" />
<!-- These buttons stay at Global Size -->
<StackPanel controls:FlowerySizeManager.IgnoreGlobalSize="True">
<controls:DaisyButton Size="Small" Content="Cancel" />
<controls:DaisyButton Size="Small" Content="Save" />
</StackPanel>
</UserControl>
| Scenario | Recommended Approach |
|---|---|
| Standard desktop app | Global Size only – simple, user-controlled |
| Accessibility needs | Global Size – discrete tiers are clearer |
| Data-dense responsive form | Auto Scaling on that specific page |
| Dashboard with charts/data | Auto Scaling for continuous responsiveness |
| Navigation/sidebar/toolbar | Global Size only – never use Auto Scaling |
For comprehensive documentation on FloweryScaleManager, including configuration, custom control support, and helper methods, see FloweryScaleManager.