Card
An interactive page: C# runs over a Blazor Server connection.
Usage
<Card Title="Website" Description="Updated 2 hours ago">
<TextBlock>Marketing pages and the docs, deployed from main.</TextBlock>
<CardFooter Justify="Justify.End">
<Button Href="projects/website" Size="ControlSize.Sm">Open</Button>
</CardFooter>
</Card>
@* The whole card is a link, through its title. *@
<Card Title="Course app" Description="12 lessons" Href="courses/app" />A card frames one thing people look at or act on, such as a project, a person or a plan, and often sits in a grid with others like it. For a band across the page, such as a hero, use a Section.
Variants
Use Variant for Outline (the default), Elevated or Filled, and Title and Description for the header.
Preview
Website
Updated 2 hours ago
Marketing pages and the docs, deployed from main.
Mobile app
Updated yesterday
The iOS and Android apps, released every two weeks.
Billing API
Updated Oct 12
Invoices, payments and refunds for every plan.
Code
<Row Gap="4" Wrap Align="Align.Stretch" Grow>
<Card Title="Website" Description="Updated 2 hours ago" Grow Basis="14.Rem">
<TextBlock Color="Color.Muted">Marketing pages and the docs, deployed from main.</TextBlock>
</Card>
<Card Variant="CardVariant.Elevated" Title="Mobile app" Description="Updated yesterday" Grow Basis="14.Rem">
<TextBlock Color="Color.Muted">The iOS and Android apps, released every two weeks.</TextBlock>
</Card>
<Card Variant="CardVariant.Filled" Title="Billing API" Description="Updated Oct 12" Grow Basis="14.Rem">
<TextBlock Color="Color.Muted">Invoices, payments and refunds for every plan.</TextBlock>
</Card>
</Row>The title is an h3; set TitleLevel to fit the page's outline. Content between the tags is the body.
Sizes
Use Size for the padding and the title's size (Md by default): Sm for dense grids, Lg for a card on its own.
Preview
Small
For dense grids and side panels
Less padding and a smaller title.
Medium
The default
The padding and title most cards use.
Large
For a card on its own
More room around everything.
Code
<Row Gap="4" Wrap Align="Align.Start" Grow>
<Card Size="ControlSize.Sm" Title="Small" Description="For dense grids and side panels" Grow Basis="12.Rem">
<TextBlock Color="Color.Muted">Less padding and a smaller title.</TextBlock>
</Card>
<Card Title="Medium" Description="The default" Grow Basis="12.Rem">
<TextBlock Color="Color.Muted">The padding and title most cards use.</TextBlock>
</Card>
<Card Size="ControlSize.Lg" Title="Large" Description="For a card on its own" Grow Basis="12.Rem">
<TextBlock Color="Color.Muted">More room around everything.</TextBlock>
</Card>
</Row>A linked card
Use Href to make the whole card a link through its title; buttons in CardActions, CardFooter and the body stay clickable on their own.
Preview
Website
izzyblazor.dev
Course app
Lessons and progress
12 lessons · 3 hours
Code
NavigationManager Navigation
<Row Gap="4" Wrap Align="Align.Stretch" Grow>
<Card Title="Website" Description="izzyblazor.dev" Href="Navigation.GetUriWithQueryParameter("project", "website")" Grow Basis="16.Rem">
<CardActions>
<IconButton Icon="Lucide.Star" Label="Add to favorites" Variant="ButtonVariant.Ghost" Accent="Accent.Neutral" Size="ControlSize.Sm" />
</CardActions>
<Row Gap="2" Wrap>
<Badge Status="Status.Success" Dot>Deployed</Badge>
<Badge>Blazor</Badge>
</Row>
<CardFooter>
<TextBlock As="span" Size="TextSize.Xs" Color="Color.Muted">3 contributors</TextBlock>
</CardFooter>
</Card>
<Card Variant="CardVariant.Elevated" Title="Course app" Description="Lessons and progress" Href="Navigation.GetUriWithQueryParameter("project", "course")" Grow Basis="16.Rem">
<CardMedia>
<svg viewBox="0 0 400 140" preserveAspectRatio="xMidYMid slice" style="height: 8rem" aria-hidden="true">
<defs><linearGradient id="course-cover" x1="0" x2="1"><stop offset="0" stop-color="#4f46e5" /><stop offset="1" stop-color="#0ea5e9" /></linearGradient></defs>
<rect width="400" height="140" fill="url(#course-cover)" />
</svg>
</CardMedia>
<TextBlock Color="Color.Muted">12 lessons · 3 hours</TextBlock>
</Card>
</Row>The link is the title, so a linked card needs a Title. CardMedia draws an image, video or SVG across the top, edge to edge; one that only decorates gets alt="" on an img or aria-hidden="true" on an svg. On a linked card an image is part of the link, and a video's controls stay usable above it.
Your own heading
Use CardHeader for content above the title, such as who wrote it, and CardActions for buttons or a Menu at the end of the heading row.
Preview
The Q3 roadmap is ready
Three themes this quarter: faster builds, a calmer on-call week and the new billing pages. Comments are open until Friday.
Code
<Card Title="The Q3 roadmap is ready" Grow MaxWidth="28.Rem">
<CardHeader>
<Row Gap="2" Align="Align.Center">
<Avatar Name="Maya Reyes" Size="AvatarSize.Sm" Decorative />
<TextBlock As="span" Size="TextSize.Sm" Weight="FontWeight.Medium">Maya Reyes</TextBlock>
<TextBlock As="span" Size="TextSize.Sm" Color="Color.Muted">2 hours ago</TextBlock>
</Row>
</CardHeader>
<CardActions>
<Menu Placement="Placement.BottomEnd">
<Trigger>
<IconButton Icon="Lucide.Ellipsis" Label="Post actions" Variant="ButtonVariant.Ghost" Accent="Accent.Neutral" Size="ControlSize.Sm" @attributes="context" />
</Trigger>
<ChildContent>
<MenuItem Icon="Lucide.Pin">Pin to the top</MenuItem>
<MenuItem Icon="Lucide.Link">Copy link</MenuItem>
</ChildContent>
</Menu>
</CardActions>
<TextBlock>Three themes this quarter: faster builds, a calmer on-call week and the new billing pages. Comments are open until Friday.</TextBlock>
<CardFooter>
<Button Variant="ButtonVariant.Outline" Accent="Accent.Neutral" Size="ControlSize.Sm" StartIcon="Lucide.MessageCircle">Comment</Button>
<Button Variant="ButtonVariant.Outline" Accent="Accent.Neutral" Size="ControlSize.Sm" StartIcon="Lucide.Share2">Share</Button>
</CardFooter>
</Card>Body and footer
Use CardBody for the body's layout, with Gap, Align and Direction, and CardFooter for a row of buttons at the bottom, with Justify.
Write the footer last, directly in the card: inside a CardBody or a form it's an ordinary row, not the card's footer.
Flush content
Use Flush on a CardBody to run a Table or a divided list to the card's edges.
Preview
Recent orders
Last 7 days
| Order | Customer | Total |
|---|---|---|
| #1042 | Ada Lovelace | $128 |
| #1041 | Grace Hopper | $64 |
| #1040 | Alan Turing | $312 |
Code
<Card Title="Recent orders" Description="Last 7 days" Grow MaxWidth="32.Rem">
<CardActions>
<Button Href="docs/components/table" Variant="ButtonVariant.Ghost" Size="ControlSize.Sm">View all</Button>
</CardActions>
<CardBody Flush>
<Table Items="RecentOrders" Caption="Recent orders" QueryPrefix="recent-">
<PropertyColumn Property="o => o.Number" Title="Order" />
<PropertyColumn Property="o => o.Customer" />
<PropertyColumn Property="o => o.Total" Format="C0" />
</Table>
</CardBody>
</Card>Sections and a footer bar
Use Dividers to make each CardBody a section with a line between, and give the CardFooter a Bg or BorderTop to make it a bar across the bottom.
Preview
Pro plan
Renews March 3, 2027
$240 / year
12 of 20 seats in use, billed to the card ending 4242.
Code
<Card Dividers Title="Pro plan" Description="Renews March 3, 2027" Grow MaxWidth="30.Rem">
<CardBody Gap="1">
<TextBlock Size="TextSize.Xl2" Weight="FontWeight.Semibold">$240 / year</TextBlock>
<TextBlock Size="TextSize.Sm" Color="Color.Muted">12 of 20 seats in use, billed to the card ending 4242.</TextBlock>
</CardBody>
<CardBody Gap="3">
<Progress Value="64" Label="Storage" ValueText="64 of 100 GB" Size="ControlSize.Sm" />
<Progress Value="38" Label="Build minutes" ValueText="1,140 of 3,000" Size="ControlSize.Sm" />
</CardBody>
<CardFooter Justify="Justify.End" Bg="Color.FillSubtle" BorderTop="1">
<Button Variant="ButtonVariant.Ghost" Accent="Accent.Neutral" Size="ControlSize.Sm">Cancel plan</Button>
<Button Size="ControlSize.Sm">Upgrade</Button>
</CardFooter>
</Card>A form in a card
Put the Form around the card, so the submit button in its CardFooter is inside the form.
Preview
Code
System.ComponentModel.DataAnnotations
@* The Form goes around the Card, so the Save button in the CardFooter is inside the form. *@
<Form Model="Model" FormName="card-settings" OnValidSubmit="Save" Grow MaxWidth="32.Rem">
<Card Dividers Title="Workspace" Description="Seen by everyone in it">
<CardBody>
<TextField @bind-Value="Model!.Name" />
</CardBody>
<CardBody>
<Switch @bind-Value="Model!.WeeklySummary" ControlPosition="ControlPosition.End" Hint="Every Monday, to each member." />
</CardBody>
<CardFooter Justify="Justify.End" Bg="Color.FillSubtle" BorderTop="1">
<Button Submit Size="ControlSize.Sm">Save</Button>
</CardFooter>
</Card>
if (_saved is not null)
{
<Alert Status="Status.Success">Saved: _saved</Alert>
}
</Form>
{
[SupplyParameterFromForm(FormName = "card-settings")]
private WorkspaceSettings? Model { get; set; }
private string? _saved;
protected override void OnInitialized() => Model ??= new();
// What was saved, not the fields: on an interactive page they change as people type.
private void Save() => _saved = $"{Model!.Name}, {(Model.WeeklySummary ? "with" : "without")} the weekly summary.";
}Live: Save runs C# on the server, with no post.
A CardFooter inside a form isn't drawn as the card's footer, and CardMedia, CardHeader and CardActions are drawn at the card's level, so a form inside the card reaches none of them. A form whose buttons are in its own FormActions can go inside.
Cards in a grid
Use a Grid with MinChildWidth to fit as many cards to a row as there's room for. Cards in a row take its height, and a CardFooter stays at the bottom.
Preview
Website
Updated 2 hours ago
Marketing pages and the docs.
Mobile app
Updated yesterday
The iOS and Android apps, released every two weeks from the release branch.
Billing API
Updated Oct 12
Invoices, payments and refunds.
Code
<Grid MinChildWidth="14.Rem" Gap="4" Grow>
foreach (var project in AllProjects)
{
<Card Title="project.Name" Description="project.Updated" Size="ControlSize.Sm">
<TextBlock Color="Color.Muted">project.Summary</TextBlock>
<CardFooter>
<Badge Status="project.Status" Dot>project.StatusText</Badge>
</CardFooter>
</Card>
}
</Grid>Put the body's text in an element, such as a TextBlock: above a footer, bare text gets the body's gap, not a section's space.
Parts
Written inside Card. The API page lists their parameters.
CardMedia: an image or video at the top of a Card, edge to edge.CardHeader: custom heading content in a Card, above its Title, such as an avatar row, beside any CardActions.CardActions: buttons at the end of a Card's heading row, such as a menu.CardBody: a Card's body with layout props: a column with Gap, Align, Justify and Direction, like Stack.CardFooter: the bottom row of a Card, such as buttons or metadata.
Mode support
| Feature | Off | Static | Live |
|---|---|---|---|
| Everything | Yes | Yes | Yes |
Off: JavaScript disabled. Static: a static SSR page with IzzyBlazor's script. Live: an interactive page (Server, WebAssembly or Auto).
Accessibility
Titlerenders a real heading,h3by default; setTitleLevelto fit the page's outline.- With
Href, the link is the title alone, so its name is theTitletext, not the whole card. It needs aTitle, and throws without one. - Keyboard users tab to the title link, and the focus ring is drawn around the whole card.
- Links and buttons in the header, CardActions, CardFooter and the body stay their own tab stops and stay clickable above the stretched link.
- CardFooter is drawn last but stays where it's written in the DOM, which is the order screen readers follow, so write it last.
Parameters
| Prop | Type | Default |
|---|---|---|
TitleThe heading. | string? | |
TitleLevelThe heading level of Title, 1 to 6. | int | 3 |
DescriptionA muted line under the title. | string? | |
ChildContentThe card's content: the body, plus any CardMedia, CardHeader, CardActions, CardBody and CardFooter. | RenderFragment? | |
HrefMakes the whole card a link to this address, through its title. | string? | |
DividersMakes each CardBody a section, with a line across the card between sections, as in a settings page. | bool | false |
VariantHow it's drawn. | CardVariant | CardVariant.Outline |
SizeInner spacing and title size. | ControlSize | ControlSize.Md |
Plus 25 surface props, 16 item props and 4 common props.
Full APISee also
- Section: a full-width band of a page, such as a hero.
- Stat: a figure with a trend read as words.
- DescriptionList: terms and their details.
- Demos: Profile card.