Skip to content
Back to skills

Avalonia Styling

ASecurity

Use when applying styles, control themes, pseudoclasses, style selectors, theme variants, or custom fonts in Avalonia. Covers Style vs ControlTheme distinction, selector syntax, nested styles, light/dark theme variants, style sharing via avares://, StyleKeyOverride, and style precedence rules.

  • 37 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 10, 2026
designgoreactgit

Works with

  • cli

Security analysis

A100/100

Scanned September 10, 2026

npx -y skills add linuxdevel/Avalonia-skills --skill avalonia-styling --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Avalonia Styling?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Avalonia Styling
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/linuxdevel-avalonia-styling/badge)](https://www.skillsdirectory.com/skills/linuxdevel-avalonia-styling)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: avalonia-styling
description: Use when applying styles, control themes, pseudoclasses, style selectors, theme variants, or custom fonts in Avalonia. Covers Style vs ControlTheme distinction, selector syntax, nested styles, light/dark theme variants, style sharing via avares://, StyleKeyOverride, and style precedence rules.
---

# Avalonia Styling

## Overview

Three mechanisms for visual styling in Avalonia:

| Mechanism | Analogous to | Use for |
|---|---|---|
| `Style` | CSS | App-specific visual rules, typography, spacing, state |
| `ControlTheme` | WPF Style + ControlTemplate | Restyling entire control appearance (lookless) |
| `ContainerQuery` | CSS container queries | Responsive styles based on container size |

Styles cascade up the logical tree. ControlThemes live in `Resources`, not `Styles`.

---

## Writing Styles

Selector + Setters. Place in `Window.Styles`, `UserControl.Styles`, or `App.axaml` for global.

```xml
<Window.Styles>
    <Style Selector="TextBlock.h1">
        <Setter Property="FontSize" Value="24"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <!-- Nested: ^ refers to parent selector (TextBlock.h1) -->
        <Style Selector="^:pointerover">
            <Setter Property="Foreground" Value="Red"/>
        </Style>
    </Style>
</Window.Styles>
```

Multiple setters, one selector:
```xml
<Style Selector="Button.primary">
    <Setter Property="Background" Value="#0078D4"/>
    <Setter Property="Foreground" Value="White"/>
    <Setter Property="Padding" Value="16,8"/>
</Style>
```

---

## Style Selector Syntax

| Selector | Syntax | Matches |
|---|---|---|
| Type | `Button` | All Buttons |
| Class | `.myClass` | Controls with that style class |
| Type + Class | `Button.primary` | Buttons with class `primary` |
| Name | `#myName` | Control with `x:Name="myName"` |
| Direct child | `StackPanel > Button` | Button as direct child of StackPanel |
| Descendant | `StackPanel Button` | Any Button inside StackPanel |
| Pseudoclass | `:pointerover` | State-based match |
| Property value | `[IsChecked=True]` | Property equals value |
| Template part | `/template/ ContentPresenter` | Element inside ControlTemplate |
| Nesting | `^` | Parent selector (nested styles only) |
| Or | `Button, TextBlock` | Either type |
| Not | `:not(.primary)` | Negation |
| Is (type check) | `:is(Button)` | Includes subtypes |

---

## Pseudoclasses

Built-in: `:pointerover`, `:pressed`, `:disabled`, `:focus`, `:focus-within`, `:focus-visible`, `:checked`, `:unchecked`, `:indeterminate`, `:selected`, `:expanded`, `:collapsed`, `:empty`, `:nth-child(n)`, `:nth-last-child(n)`, `:first-child`, `:last-child`

Custom pseudoclass in code-behind or ViewModel:
```csharp
// In a custom control
PseudoClasses.Set(":loading", isLoading);
```

Then target in XAML:
```xml
<Style Selector="local|MyControl:loading">
    <Setter Property="Opacity" Value="0.5"/>
</Style>
```

---

## Style Classes

Declare on control:
```xml
<Button Classes="primary large">Click</Button>
```

Add/remove in code:
```csharp
myButton.Classes.Add("active");
myButton.Classes.Remove("active");
myButton.Classes.Set("active", condition); // toggle
```

Conditional class binding:
```xml
<Button Classes.active="{Binding IsActive}"/>
```

Multiple classes:
```xml
<Button Classes.primary="{Binding IsPrimary}" Classes.large="{Binding IsLarge}"/>
```

---

## Control Themes

ControlThemes replace the entire visual tree of a control. Must go in `Resources`, not `Styles`.

```xml
<Application.Resources>
    <ControlTheme x:Key="{x:Type Button}" TargetType="Button">
        <Setter Property="Background" Value="#E0E0E0"/>
        <Setter Property="Template">
            <ControlTemplate>
                <Border Background="{TemplateBinding Background}"
                        CornerRadius="4"
                        Padding="{TemplateBinding Padding}">
                    <ContentPresenter Content="{TemplateBinding Content}"/>
                </Border>
            </ControlTemplate>
        </Setter>
        <!-- State styles inside ControlTheme -->
        <Style Selector="^:pointerover /template/ Border">
            <Setter Property="Background" Value="#C0C0C0"/>
        </Style>
        <Style Selector="^:pressed /template/ Border">
            <Setter Property="Background" Value="#A0A0A0"/>
        </Style>
    </ControlTheme>
</Application.Resources>
```

Extend existing theme with `BasedOn`:
```xml
<ControlTheme x:Key="OutlineButton" TargetType="Button"
              BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="BorderThickness" Value="2"/>
    <Setter Property="Background" Value="Transparent"/>
</ControlTheme>
```

Apply a named ControlTheme:
```xml
<Button Theme="{StaticResource OutlineButton}">Outlined</Button>
```

---

## Theme Variants (Light / Dark)

Set on Window or Application:
```xml
<Window RequestedThemeVariant="Dark">
```

```csharp
Application.Current!.RequestedThemeVariant = ThemeVariant.Dark;
```

Theme-variant resources:
```xml
<ResourceDictionary>
    <ResourceDictionary.ThemeDictionaries>
        <ResourceDictionary x:Key="Light">
            <SolidColorBrush x:Key="SurfaceBrush" Color="#FFFFFF"/>
        </ResourceDictionary>
        <ResourceDictionary x:Key="Dark">
            <SolidColorBrush x:Key="SurfaceBrush" Color="#1E1E1E"/>
        </ResourceDictionary>
    </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
```

Consume with `DynamicResource` (not `StaticResource`):
```xml
<Border Background="{DynamicResource SurfaceBrush}"/>
```

---

## Built-in Themes

```xml
<!-- App.axaml -->
<Application.Styles>
    <FluentTheme/>
    <!-- or -->
    <SimpleTheme/>
</Application.Styles>
```

NuGet packages:
- `Avalonia.Themes.Fluent` — Microsoft Fluent design
- `Avalonia.Themes.Simple` — minimal, no external dependencies

---

## Sharing Styles

Include an external `.axaml` file:
```xml
<Window.Styles>
    <StyleInclude Source="avares://MyApp/Styles/Buttons.axaml"/>
</Window.Styles>
```

Or at app level:
```xml
<Application.Styles>
    <FluentTheme/>
    <StyleInclude Source="avares://MyApp/Styles/Global.axaml"/>
</Application.Styles>
```

Merge ResourceDictionary:
```xml
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceInclude Source="avares://MyApp/Resources/Colors.axaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
```

`avares://` URI scheme references embedded resources from the assembly. The format is `avares://AssemblyName/Path/To/File.axaml`.

---

## StyleKeyOverride

Causes a custom control subclass to pick up styles targeting its base type:
```csharp
public class MyButton : Button
{
    // This control will be styled as Button, not MyButton
    protected override Type StyleKeyOverride => typeof(Button);
}
```

Useful when subclassing a control only for behavior changes, not visual identity.

---

## ContainerQuery (Responsive Styles)

```xml
<Style Selector="local|MyPanel">
    <Style Selector="^ /template/ TextBlock">
        <ContainerQuery MinWidth="400">
            <Setter Property="FontSize" Value="18"/>
        </ContainerQuery>
        <ContainerQuery MaxWidth="399">
            <Setter Property="FontSize" Value="12"/>
        </ContainerQuery>
    </Style>
</Style>
```

---

## Style Precedence (Highest to Lowest)

1. Inline property set (e.g., `<Button Background="Red"/>`)
2. Animations
3. Template bindings (`{TemplateBinding}`)
4. Local style (closest scope — Window or UserControl)
5. Inherited styles (further up logical tree — App.axaml)

---

## Community Themes & Icon Libraries

### Themes
| Theme | NuGet / Repo | Style |
|---|---|---|
| Material.Avalonia | `Material.Avalonia` | Google Material Design theme |
| Semi.Avalonia | `Semi.Avalonia` | Semi Design (modern, clean) |
| SukiUI | `SukiUI` | Flat design, highly customizable |
| ShadUI | GitHub: accntech/shad-ui | shadcn/ui inspired, modern |
| FluentAvalonia | `FluentAvalonia` | WinUI3 Fluent controls + theme |
| Ursa.Avalonia | `Irihi.Ursa` | Full UI library with rich controls |
| AntDesign.Avalonia | GitHub: MicroSugarDeveloperOrg/AntDesign.Avalonia | Ant Design theme |
| Neumorphism.Avalonia | GitHub: flarive/Neumorphism.Avalonia | Neumorphism soft-UI design |
| Classic.Avalonia | GitHub: BAndysc/Classic.Avalonia | Windows 9x retro theme |
| Pipboy.Avalonia | GitHub: NeverMorewd/Pipboy.Avalonia | Fallout 4 Pip-Boy inspired theme |
| Huskui.Avalonia | GitHub: d3ara1n/Huskui.Avalonia | Modern, ParkUI/Radix-inspired |
| Citrus.Avalonia | `Citrus.Avalonia` | Modern styles for built-in controls |
| WPFDarkTheme | GitHub: AngryCarrot789/WPFDarkTheme | Compact soft dark theme |

### Icon Libraries
| Library | NuGet | Icons |
|---|---|---|
| Icons.Avalonia | `Projektanker.Icons.Avalonia` | FontAwesome, Material, and more |
| IconPacks.Avalonia | `MahApps.Metro.IconPacks.Avalonia` | 21,000+ icons from multiple packs |
| Material.Icons.Avalonia | `Material.Icons.Avalonia` | 6000+ Material Design Icons |
| HeroIcons.Avalonia | GitHub: russkyc/heroicons-avalonia | Heroicons set |
| Lucide.Avalonia | `Lucide.Avalonia` | Lucide icon library |

### CSS-like Styling
- **Nlnet.Avalonia.Css** — write Avalonia styles in CSS syntax (`Nlnet.Avalonia.Css`)

---

## Common Mistakes

- **Using WPF `Triggers`** — does not exist in Avalonia. Use pseudoclasses + nested styles instead.
- **Forgetting `^` in nested selectors** — `<Style Selector=":pointerover">` inside another Style does not scope to the parent; must be `<Style Selector="^:pointerover">`.
- **Putting ControlTheme in `Window.Styles`** — ControlThemes must go in `Window.Resources` or `Application.Resources`, not `Styles`.
- **Using `StaticResource` for theme-variant resources** — theme variant resources must be referenced with `DynamicResource` to react to variant changes at runtime.
- **Confusing Styles and ControlThemes** — Styles add/override individual property values; ControlThemes replace the entire visual template. If you only need color or font changes, use a Style.
- **`/template/` selector outside ControlTheme** — the `/template/` segment only works when targeting elements inside a ControlTemplate, typically from within a ControlTheme state style.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.