YogaLayout
YogaLayout brings the layout model of Yoga to .NET MAUI and Blazor. It
is flexbox with Yoga’s defaults and extras. The same properties give the same boxes on both hosts.
Features
Section titled “Features”- No native code. On MAUI a pure C# engine lays children out. On Blazor the browser’s flexbox does the work, set up with Yoga’s defaults.
- Yoga defaults: column direction,
FlexShrink0,AlignContentFlexStart, minimum size 0, border-box, relative position. - Absolute positioning with
Left/Top/Right/Bottom/Start/Endinsets against the padding box. - Percentages for sizes, min/max, basis and insets:
"50%". AspectRatio. One known dimension, including a stretched one, gives the other.- Auto margins (
AutoMargins="Start") push a child to the end of its line or centre it. - Gaps:
Gap,RowGap,ColumnGap. - Right-to-left flow.
Start/Endfollow the flow direction.
AI Skill
Section titled “AI Skill”Step 1 — Add the marketplace:
claude plugin marketplace add shinyorg/skillsStep 2 — Install the plugin:
claude plugin install shiny@shinyOne plugin installs all 37 Shiny skills. Your agent loads only the skill relevant to what you're building, so there's no cost to having them all available.
Step 1 — Add the marketplace:
copilot plugin marketplace add https://github.com/shinyorg/skillsStep 2 — Install the plugin:
copilot plugin install shiny@shinyOne plugin installs all 37 Shiny skills. Your agent loads only the skill relevant to what you're building, so there's no cost to having them all available.
How Yoga differs from CSS flexbox
Section titled “How Yoga differs from CSS flexbox”| CSS | Yoga / YogaLayout |
|
|---|---|---|
FlexDirection default |
row | Column |
FlexShrink default |
1 | 0 |
AlignContent default |
stretch | FlexStart |
| Minimum size | auto (content) |
0 |
| Box sizing | content-box | border-box |
| Position default | static | Relative |
Child properties are attached, so they work on any view.
xmlns:shiny="http://shiny.net/maui/controls"
<shiny:YogaLayout FlexDirection="Row" Gap="12"> <shiny:YogaLayout shiny:YogaLayout.FlexGrow="1" shiny:YogaLayout.FlexBasis="0"> <!-- The column stretches the image across; AspectRatio derives its height. --> <Image Source="card.png" Aspect="AspectFill" shiny:YogaLayout.AspectRatio="1.5" /> <Label Text="Aurora" Margin="8" /> <Border shiny:YogaLayout.PositionType="Absolute" shiny:YogaLayout.Top="8" shiny:YogaLayout.Right="8"> <Label Text="NEW" /> </Border> </shiny:YogaLayout> <BoxView shiny:YogaLayout.NodeWidth="25%" /></shiny:YogaLayout>In C#, lengths are YogaValue: YogaLayout.SetNodeWidth(view, YogaValue.Percent(50)),
YogaLayout.SetLeft(view, 10). A double converts implicitly.
Blazor
Section titled “Blazor”Every Yoga node is a <YogaLayout>, the way every React Native view is a node. Lengths are strings,
because Razor would read a bare 50% as C#.
<YogaLayout FlexDirection="YogaFlexDirection.Row" AlignItems="YogaAlign.Center" Gap="8" Padding="8 12"> <YogaLayout FlexGrow="1"><strong>Inbox</strong></YogaLayout> <YogaLayout AutoMargins="YogaEdges.Start">Done</YogaLayout> <YogaLayout PositionType="YogaPositionType.Absolute" Top="8" Right="8" Width="24" AspectRatio="1" /></YogaLayout>Plain elements placed directly inside a YogaLayout get Yoga’s flex-shrink: 0, border-box and minimum
size 0. The rule is in a CSS cascade layer, so any style of your own on the element still wins.
Properties
Section titled “Properties”Container
Section titled “Container”| Property | Default | |
|---|---|---|
FlexDirection |
Column |
Column, ColumnReverse, Row, RowReverse |
JustifyContent |
FlexStart |
FlexStart, Center, FlexEnd, SpaceBetween, SpaceAround, SpaceEvenly |
AlignItems |
Stretch |
FlexStart, Center, FlexEnd, Stretch, Baseline |
AlignContent |
FlexStart |
also the Space* values; applies to wrapped lines |
FlexWrap |
NoWrap |
NoWrap, Wrap, WrapReverse |
Gap / RowGap / ColumnGap |
0 | the per-axis gaps override Gap |
Padding |
MAUI Thickness; Blazor CSS shorthand (bare numbers are px) |
|
| Direction | inherit | MAUI FlowDirection; Blazor Direction (Inherit, LTR, RTL) |
| Property | Default | |
|---|---|---|
FlexGrow / FlexShrink |
0 / 0 | |
FlexBasis |
auto |
points or % |
AlignSelf |
Auto |
overrides AlignItems |
PositionType |
Relative |
Absolute leaves the flow; Static ignores insets |
Left Top Right Bottom Start End |
insets, points or % |
|
Width / Height (Blazor), NodeWidth / NodeHeight (MAUI) |
auto |
points or % |
MinWidth MinHeight MaxWidth MaxHeight |
points or % |
|
AspectRatio |
width ÷ height | |
AutoMargins |
None |
YogaEdges flags: Left, Top, Right, Bottom, Start, End, Horizontal, Vertical, All |
Display |
Flex |
None removes the child from layout |
Platform notes
Section titled “Platform notes”- Baseline on MAUI: MAUI exposes no text baselines, so
Baselinealigns each child’s bottom edge, as Yoga does for a node without a baseline function. Blazor aligns real text baselines. - Margins on MAUI are physical.
Margin.Leftstays on the left in right-to-left flow. UseStart/Endfor flow-relative insets and auto margins. - Absolute children are measured against the container’s padding box and add nothing to its size. An
axis with no insets falls back to where
JustifyContent/AlignItemswould place a lone child. - Need FlexLayout’s API instead? ShinyFlexLayout is a cached, drop-in
replacement for MAUI’s
FlexLayout.


