Starter
£0 per month
- One workspace
- Community support
Containers
TwFlex is a Blazor flexbox component: responsive direction, wrapping, alignment, gaps and dividers, with TwFlexItem to size and order each child.
Last updated
TwFlex lays its children out in a row. Gap sets the space between them as a step on Tailwind's spacing scale, such as 3 for gap-3.<TwFlex Wrap="FlexWrap.Wrap" Align="AlignItems.Center" Gap="3" Class="rounded-xl bg-white p-3 shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:ring-white/10">
<TwButton Label="Publish" Color="Color.Primary" StartIcon="Icon.Rocket_Takeoff" />
<TwButton Label="Save draft" Color="Color.Primary" Variant="ButtonVariant.Outlined" StartIcon="Icon.Pencil" />
<TwButton Label="Share" Color="Color.Primary" Variant="ButtonVariant.Text" StartIcon="Icon.Share" />
</TwFlex>Direction to Col to stack children. Add DirectionSm, DirectionMd, DirectionLg, DirectionXl or DirectionXl2 to change direction from that breakpoint up: these steps stack on a phone and sit in a row from md.Step 1
Choose a plan
Pick the plan that suits you.
Step 2
Connect your bank
Link your account securely.
Step 3
Watch it grow
Savings add up automatically.
<TwFlex Element="LayoutElement.Ol" Direction="FlexDirection.Col" DirectionMd="FlexDirection.Row" Gap="4">
@foreach (var step in _steps)
{
<TwFlexItem Element="LayoutElement.Li" Flex="FlexSize.Fill" Class="rounded-xl bg-white p-5 shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:ring-white/10">
<TwFlex Align="AlignItems.Center" Gap="3">
<span class="flex size-10 items-center justify-center rounded-lg bg-linear-to-br from-purple-600 to-fuchsia-700 text-lg text-white shadow-sm shadow-purple-600/30">
<TwIcon Icon="@step.Icon" />
</span>
<p class="text-xs font-semibold uppercase tracking-wide text-purple-700 dark:text-purple-300">Step @step.Number</p>
</TwFlex>
<p class="mt-3 font-semibold text-gray-900 dark:text-white">@step.Title</p>
<p class="mt-1 text-sm text-gray-600 dark:text-gray-300">@step.Text</p>
</TwFlexItem>
}
</TwFlex>@code {
private sealed record Step(int Number, string Title, string Text, Icon Icon);
private static readonly Step[] _steps =
[
new(1, "Choose a plan", "Pick the plan that suits you.", Icon.Wallet2),
new(2, "Connect your bank", "Link your account securely.", Icon.Shield_Check),
new(3, "Watch it grow", "Savings add up automatically.", Icon.Piggy_Bank)
];
}Justify to space children along the main axis: Start, Center, End, Between, Around or Evenly.Justify="JustifyContent.Start"
Justify="JustifyContent.Center"
Justify="JustifyContent.End"
Justify="JustifyContent.Between"
Justify="JustifyContent.Around"
Justify="JustifyContent.Evenly"
<TwFlex Direction="FlexDirection.Col" Gap="3">
@foreach (var justify in _justify)
{
<div>
<p class="mb-1.5 font-mono text-xs text-gray-600 dark:text-gray-400">Justify="JustifyContent.@justify"</p>
<TwFlex Justify="justify" Gap="2" Class="rounded-xl bg-gray-50 bg-[radial-gradient(var(--color-gray-300)_1px,transparent_1px)] bg-size-[14px_14px] p-2 ring-1 ring-gray-900/5 dark:bg-gray-950/40 dark:bg-[radial-gradient(var(--color-gray-700)_1px,transparent_1px)] dark:ring-white/10">
@foreach (var icon in _justifyIcons)
{
<span class="flex size-9 items-center justify-center rounded-lg bg-white text-purple-700 shadow-sm ring-1 ring-gray-900/10 dark:bg-gray-800 dark:text-purple-300 dark:ring-white/10">
<TwIcon Icon="icon" />
</span>
}
</TwFlex>
</div>
}
</TwFlex>Align to align children of different heights on the cross axis: Start, Center, End, Stretch (the default) or Baseline, which lines up their text.Align="AlignItems.Start"
Align="AlignItems.Center"
Align="AlignItems.End"
Align="AlignItems.Stretch"
Align="AlignItems.Baseline"
<TwGrid Cols="1" ColsSm="2" ColsLg="3" Gap="4">
@foreach (var align in _align)
{
<div>
<p class="mb-1.5 font-mono text-xs text-gray-600 dark:text-gray-400">Align="AlignItems.@align"</p>
<TwFlex Align="align" Gap="2" Class="h-28 rounded-xl bg-gray-50 bg-[radial-gradient(var(--color-gray-300)_1px,transparent_1px)] bg-size-[14px_14px] p-2 ring-1 ring-gray-900/5 dark:bg-gray-950/40 dark:bg-[radial-gradient(var(--color-gray-700)_1px,transparent_1px)] dark:ring-white/10">
<span class="rounded-lg bg-purple-600 px-3 py-1 text-sm font-medium text-white shadow-sm">Short</span>
<span class="rounded-lg bg-fuchsia-700 px-3 py-4 text-lg font-medium text-white shadow-sm">Tall</span>
<span class="rounded-lg bg-indigo-600 px-3 py-2 text-xs font-medium text-white shadow-sm">Small</span>
</TwFlex>
</div>
}
</TwGrid>Wrap to let children flow onto new lines. ColGap and RowGap space columns and rows separately, and AlignContent spaces the wrapped lines.<div class="rounded-xl bg-white p-4 shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:ring-white/10">
<TwFlex Align="AlignItems.Center" Gap="2" Class="mb-3 text-sm font-semibold text-gray-900 dark:text-white">
<TwIcon Icon="Icon.Funnel" Class="text-purple-700 dark:text-purple-300" />
Filter by topic
</TwFlex>
<TwFlex Element="LayoutElement.Ul" Wrap="FlexWrap.Wrap" ColGap="2" RowGap="3" AriaLabel="Topics">
@foreach (var (topic, selected) in _topics)
{
<li><TwChip Label="@topic" Color="Color.Primary" Variant="@(selected ? ButtonVariant.Filled : ButtonVariant.Outlined)" StartIcon="@(selected ? Icon.Check_Lg : (Icon?)null)" /></li>
}
</TwFlex>
</div>@code {
private static readonly (string Topic, bool Selected)[] _topics =
[
("Accessibility", true), ("Blazor", true), ("Dark mode", false), ("Design tokens", false), ("Forms", false),
("Localization", false), ("Performance", false), ("Tailwind CSS", true), ("Testing", false), ("Theming", false)
];
}Divided to draw a line between children: down between a row, or across between a column. Render a list with Element="LayoutElement.Ul" and items with Element="LayoutElement.Li"; a list layout keeps its list meaning for screen readers.£12,480
£10,950
+13.98%
£1,162
<TwFlex Element="LayoutElement.Ul" Divided Wrap="FlexWrap.Wrap" Class="overflow-hidden rounded-xl bg-white shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:ring-white/10" AriaLabel="Account summary">
@foreach (var stat in _stats)
{
<TwFlexItem Element="LayoutElement.Li" Flex="FlexSize.Fill" Class="min-w-36 px-5 py-4">
<TwFlex Align="AlignItems.Center" Gap="2" Class="text-xs font-medium text-gray-600 dark:text-gray-300">
<TwIcon Icon="@stat.Icon" Class="text-purple-700 dark:text-purple-300" />
@stat.Label
</TwFlex>
<p class="mt-1 text-xl font-semibold tabular-nums text-gray-900 dark:text-white">@stat.Value</p>
</TwFlexItem>
}
</TwFlex>@code {
private static readonly (string Label, string Value, Icon Icon)[] _stats =
[
("Balance", "£12,480", Icon.Wallet2),
("Invested", "£10,950", Icon.Graph_Up_Arrow),
("Return", "+13.98%", Icon.Arrow_Up_Right),
("Cash", "£1,162", Icon.Piggy_Bank)
];
}TwFlexItem to control its size. Flex sets the grow and shrink shorthand: Fill takes an equal share of the space, Auto grows from its content, None keeps its size. Basis sets the starting size, and Grow and Shrink switch each behaviour on or off. In this search bar the field fills the row and the buttons keep their size; below it, a sidebar starts at a third and the content grows into the rest.Basis="FlexBasis.Third"
Grow="true"
<TwFlex Direction="FlexDirection.Col" Gap="4">
<TwFlex Align="AlignItems.End" Gap="2" Class="rounded-xl bg-white p-3 shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:ring-white/10">
<TwFlexItem Flex="FlexSize.Fill">
<TwTextfield Id="flex-search" Label="Search orders" @bind-Value="search" Placeholder="Order number or customer" type="search" />
</TwFlexItem>
<TwFlexItem Flex="FlexSize.None">
<TwButton Label="Search" Color="Color.Primary" StartIcon="Icon.Search" />
</TwFlexItem>
</TwFlex>
<TwFlex Gap="3" Class="h-32">
<TwFlexItem Basis="FlexBasis.Third" Shrink="false" Class="rounded-xl bg-purple-50 p-3 ring-1 ring-purple-600/10 dark:bg-purple-500/15 dark:ring-purple-400/20">
<p class="font-mono text-xs text-purple-800 dark:text-purple-200">Basis="FlexBasis.Third"</p>
</TwFlexItem>
<TwFlexItem Grow="true" Class="rounded-xl bg-white p-3 shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:ring-white/10">
<p class="font-mono text-xs text-gray-600 dark:text-gray-300">Grow="true"</p>
</TwFlexItem>
</TwFlex>
</TwFlex>@code {
// CodeExample 'FlexItemSizeCode' not found
}PushEnd on an item to push it, and everything after it, to the end of the layout: the end of a row, as in this file row, or the bottom of a column (see Full height below). Set MinWidthZero to let an item shrink below its content so long text inside it can truncate.Quarterly results presentation for the board, final version.pdf
2.4 MB, updated today
<TwFlex Align="AlignItems.Center" Gap="3" Class="rounded-xl bg-white p-3 shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:ring-white/10">
<span class="flex size-10 shrink-0 items-center justify-center rounded-lg bg-red-50 text-lg text-red-700 ring-1 ring-red-600/10 dark:bg-red-500/15 dark:text-red-300 dark:ring-red-400/20">
<TwIcon Icon="Icon.File_Earmark_Pdf" />
</span>
<TwFlexItem MinWidthZero>
<p class="truncate text-sm font-semibold text-gray-900 dark:text-white">Quarterly results presentation for the board, final version.pdf</p>
<p class="text-xs text-gray-600 dark:text-gray-300">2.4 MB, updated today</p>
</TwFlexItem>
<TwFlexItem PushEnd Flex="FlexSize.None">
<TwFlex Gap="2">
<TwButton Label="Share" Variant="ButtonVariant.Text" Color="Color.Primary" StartIcon="Icon.Share" Dense />
<TwButton Label="Download" Color="Color.Primary" StartIcon="Icon.Download" Dense />
</TwFlex>
</TwFlexItem>
</TwFlex>AlignSelf overrides the layout's alignment for one item. Order draws an item in another position, from 1 to 12 or ItemOrder.First and ItemOrder.Last. Order and reversed directions change only where items are drawn, not the Tab order or what a screen reader reads first, so use them for decoration and keep the markup in reading order.<TwFlex Align="AlignItems.Start" Gap="2" Class="h-28 rounded-xl bg-gray-50 bg-[radial-gradient(var(--color-gray-300)_1px,transparent_1px)] bg-size-[14px_14px] p-2 ring-1 ring-gray-900/5 dark:bg-gray-950/40 dark:bg-[radial-gradient(var(--color-gray-700)_1px,transparent_1px)] dark:ring-white/10">
<TwFlexItem Class="rounded-lg bg-white px-3 py-1.5 text-sm font-medium text-gray-800 shadow-sm ring-1 ring-gray-900/10 dark:bg-gray-800 dark:text-gray-100 dark:ring-white/10">A</TwFlexItem>
<TwFlexItem AlignSelf="AlignSelf.End" Class="rounded-lg bg-white px-3 py-1.5 text-sm font-medium text-gray-800 shadow-sm ring-1 ring-gray-900/10 dark:bg-gray-800 dark:text-gray-100 dark:ring-white/10">B, AlignSelf End</TwFlexItem>
<TwFlexItem Order="ItemOrder.First" Class="rounded-lg bg-purple-600 px-3 py-1.5 text-sm font-medium text-white shadow-sm">C, Order First</TwFlexItem>
<TwFlexItem AlignSelf="AlignSelf.Center" Class="rounded-lg bg-white px-3 py-1.5 text-sm font-medium text-gray-800 shadow-sm ring-1 ring-gray-900/10 dark:bg-gray-800 dark:text-gray-100 dark:ring-white/10">D, AlignSelf Center</TwFlexItem>
</TwFlex>FullHeight to fill the parent's height. In a column, PushEnd on an item pushes it to the bottom, so buttons line up across a row of cards of different lengths.£0 per month
£12 per month
<TwGrid Cols="1" ColsSm="2" Gap="4">
@foreach (var plan in _plans)
{
<TwCard>
<TwFlex Element="LayoutElement.Article" Direction="FlexDirection.Col" FullHeight Gap="3">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">@plan.Name</h3>
<p class="text-3xl font-semibold tracking-tight tabular-nums text-gray-900 dark:text-white">@plan.Price<span class="text-sm font-normal text-gray-600 dark:text-gray-300"> per month</span></p>
<TwFlex Element="LayoutElement.Ul" Direction="FlexDirection.Col" Gap="2" Class="text-sm text-gray-700 dark:text-gray-200">
@foreach (var feature in plan.Features)
{
<TwFlex Element="LayoutElement.Li" Align="AlignItems.Center" Gap="2">
<TwIcon Icon="Icon.Check_Lg" Class="text-purple-700 dark:text-purple-300" />
@feature
</TwFlex>
}
</TwFlex>
<TwFlexItem PushEnd Class="pt-3">
<TwButton Label="Choose plan" AriaLabel="@($"Choose plan: {plan.Name}")" Color="Color.Primary" Class="w-full" />
</TwFlexItem>
</TwFlex>
</TwCard>
}
</TwGrid>@code {
private sealed record Plan(string Name, string Price, string[] Features);
private static readonly Plan[] _plans =
[
new("Starter", "£0", ["One workspace", "Community support"]),
new("Team", "£12", ["Unlimited workspaces", "Roles and permissions", "Audit history", "Single sign-on", "Priority support"])
];
}Inline for a flex layout that sits in a line of text, such as an icon beside a word.Your order is confirmed and will arrive on Friday.
<p class="rounded-xl bg-white p-4 text-sm text-gray-700 shadow-sm ring-1 ring-gray-900/5 dark:bg-white/5 dark:text-gray-200 dark:ring-white/10">
Your order is
<TwFlex Element="LayoutElement.Span" Inline Align="AlignItems.Center" Gap="1" Class="rounded-full bg-green-50 px-2 py-0.5 font-semibold text-green-800 dark:bg-green-500/15 dark:text-green-300">
<TwIcon Icon="Icon.Check_Circle_Fill" />
confirmed
</TwFlex>
and will arrive on Friday.
</p>TwBlazorTheme.Components (a TwFlexTheme), configured via the
AddTwBlazor() options callback described on the Get Started page.
Every property is a set of Tailwind classes, so changes are picked up by your own Tailwind build.
| Property | Type | Controls |
|---|---|---|
Base |
string | |
Inline |
string | |
FullWidth |
string | |
FullHeight |
string | |
DivideX |
string | |
DivideY |
string | |
DivideXReverse |
string | |
DivideYReverse |
string | |
DivideColor |
string | |
Item |
string | |
ItemMinWidthZero |
string | |
ItemPushEnd |
string | |
ItemPushEndColumn |
string |
Direction, wrapping, alignment, basis and order come from the shared Flexbox utilities, and the gaps from Spacing, so any component theme can reuse them.
Gaps accept the steps 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20 and 24.
Full reference: TwFlexTheme on the API docs.