Card
Flexible content container with image, header, footer, and layout options, plus contextual background colors.
Overview
A <Card> is a flexible content container built with flexbox, composing options for images, headers, footers, and a wide variety of body content. A card has no top, left, or right margin by default — spacing utilities apply as needed — and no fixed width to start, so it fills the full width of its parent.
Basic usage
A basic card mixes an image, a title, body text, and a button inside a fixed width.
Card title
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereimport { Button, Card, CardBody, CardImage, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
)
}For the common case — a single image, a title, some text, maybe a footer — <Card> accepts
image/imageAlt/imageOrientation, title, subtitle, text, and footer shorthand props
directly, instead of composing CardImage/CardBody/CardTitle/CardText/CardFooter
directly. title/subtitle/text/children render together inside a single CardBody, in that
order, so children still works for trailing content like a button. This example produces the
same markup as the one above:
Card title
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereimport { Button, Card } from '@chassis-ui/react'
export const Example = () => {
return (
<Card
style={{ width: '18rem' }}
image="https://placehold.co/800x400"
title="Card title"
text="Some quick example text to build on the card title and make up the bulk of the card's content."
>
<Button href="#">Go somewhere</Button>
</Card>
)
}Shorthand props only take effect once at least one of image/title/subtitle/text/footer
is set — otherwise children render exactly as passed, so full manual composition (CardHeader,
flush lists, image overlays, nav headers, horizontal layouts, …) keeps working unchanged. Mixing
shorthand props with a manually-composed children tree (e.g. a raw CardHeader) isn't
supported — pick one approach per card, falling back to composing CardBody/CardTitle/etc.
directly for anything the shorthand props don't cover.
image also accepts a full element instead of a src string — a <CardImage> composed by hand,
a <Placeholder>, a loading
<Skeleton> — rendered as-is in the image slot, so the rest of
title/subtitle/text/footer don't have to give up their shorthand just because the image
needs something other than a plain URL. imageAlt/imageOrientation only apply to the src form;
set them directly on the passed element otherwise. See
Loading states for a worked example swapping the image for
a skeleton while data loads.
Content types
<Card> supports a wide variety of content, including images, text, lists, and links.
Body
<CardBody> is the main padded content region of a card.
import { Card, CardBody } from '@chassis-ui/react'
export const Example = () => {
return (
<Card>
<CardBody>This is some text within a card body.</CardBody>
</Card>
)
}Titles, text, and links
<CardTitle> renders a card's title, and <CardLink> renders links positioned next to each
other. <CardSubtitle> renders a subtitle — when both <CardTitle> and <CardSubtitle> sit
inside the same <CardBody>, their spacing lines up automatically.
Card title
Card subtitle
Some quick example text to build on the card title and make up the bulk of the card's content.
import { Card, CardBody, CardLink, CardSubtitle, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<CardBody>
<CardTitle>Card title</CardTitle>
<CardSubtitle className="mb-md fg-subtle">Card subtitle</CardSubtitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
<CardText>
<CardLink href="#">Card link</CardLink>
<CardLink href="#">Another link</CardLink>
</CardText>
</CardBody>
</Card>
)
}Images
orientation="top" places an image at the top of the card. <CardText> renders text content,
styled with regular HTML tags as needed.
Some quick example text to build on the card title and make up the bulk of the card's content.
import { Card, CardBody, CardImage, CardText } from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
</CardBody>
</Card>
)
}<CardImage> renders an <img> by default, but its component prop accepts any element or
component — including a framework's own Image (Next.js, Gatsby, Remix, etc.). The passed
component is fully type-checked at the call site, so its own props (fill, priority, loader,
and so on) are available and validated alongside src/alt:
import Image from 'next/image'
<CardImage component={Image} src="/hero.jpg" alt="" fill priority orientation="top" />Lists
A flush <List> renders a list of content inside a card without its own padding.
- Cras justo odio
- Dapibus ac facilisis in
- Vestibulum at eros
import { Card, List, ListItem } from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<List flush>
<ListItem>Cras justo odio</ListItem>
<ListItem>Dapibus ac facilisis in</ListItem>
<ListItem>Vestibulum at eros</ListItem>
</List>
</Card>
)
}- Cras justo odio
- Dapibus ac facilisis in
- Vestibulum at eros
import { Card, CardHeader, List, ListItem } from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<CardHeader>Header</CardHeader>
<List flush>
<ListItem>Cras justo odio</ListItem>
<ListItem>Dapibus ac facilisis in</ListItem>
<ListItem>Vestibulum at eros</ListItem>
</List>
</Card>
)
}- Cras justo odio
- Dapibus ac facilisis in
- Vestibulum at eros
import { Card, CardFooter, List, ListItem } from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<List flush>
<ListItem>Cras justo odio</ListItem>
<ListItem>Dapibus ac facilisis in</ListItem>
<ListItem>Vestibulum at eros</ListItem>
</List>
<CardFooter>Footer</CardFooter>
</Card>
)
}Kitchen sink
Image styles, body content, and a list combine inside a single fixed-width card.
Card title
Some quick example text to build on the card title and make up the bulk of the card's content.
- Cras justo odio
- Dapibus ac facilisis in
- Vestibulum at eros
import {
Card,
CardBody,
CardImage,
CardLink,
CardText,
CardTitle,
List,
ListItem
} from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
</CardBody>
<List flush>
<ListItem>Cras justo odio</ListItem>
<ListItem>Dapibus ac facilisis in</ListItem>
<ListItem>Vestibulum at eros</ListItem>
</List>
<CardBody>
<CardLink href="#">Card link</CardLink>
<CardLink href="#">Another link</CardLink>
</CardBody>
</Card>
)
}Header and footer
<CardHeader> and <CardFooter> add an optional header and/or footer to a card.
Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport { Button, Card, CardBody, CardHeader, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card>
<CardHeader>Header</CardHeader>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>With supporting text below as a natural lead-in to additional content.</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
)
}<CardHeader> accepts a component prop — component="h5", for example — to change its
rendered element.
Header
Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport { Button, Card, CardBody, CardHeader, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card>
<CardHeader component="h5">Header</CardHeader>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>With supporting text below as a natural lead-in to additional content.</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
)
}Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
import { Card, CardBody, CardHeader } from '@chassis-ui/react'
export const Example = () => {
return (
<Card>
<CardHeader>Quote</CardHeader>
<CardBody>
<figure className="mb-0">
<blockquote className="blockquote">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
</p>
</blockquote>
<figcaption className="attribution mb-0">
Someone famous in <cite title="Source Title">Source Title</cite>
</figcaption>
</figure>
</CardBody>
</Card>
)
}Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport {
Button,
Card,
CardBody,
CardFooter,
CardHeader,
CardText,
CardTitle
} from '@chassis-ui/react'
export const Example = () => {
return (
<Card className="text-center">
<CardHeader>Header</CardHeader>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>With supporting text below as a natural lead-in to additional content.</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
<CardFooter className="fg-subtle">2 days ago</CardFooter>
</Card>
)
}Sizing
A card has no specific width set by default, so it renders at 100% width unless otherwise
stated. The grid, sizing utilities, and custom CSS all adjust this as needed.
Using grid markup
A <Grid> sizes cards by the columns its items span.
Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereSpecial title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport { Button, Card, CardBody, CardText, CardTitle, Grid, GridItem } from '@chassis-ui/react'
export const Example = () => {
return (
<Grid gap="md">
<GridItem span={{ base: 'full', sm: 6 }}>
<Card>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>
With supporting text below as a natural lead-in to additional content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
</GridItem>
<GridItem span={{ base: 'full', sm: 6 }}>
<Card>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>
With supporting text below as a natural lead-in to additional content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
</GridItem>
</Grid>
)
}Using utilities
Sizing utilities set a card's width directly.
import { Button, Card, CardBody, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<>
<Card className="w-75">
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
With supporting text below as a natural lead-in to additional content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
<Card className="w-50">
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
With supporting text below as a natural lead-in to additional content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
</>
)
}Using custom CSS
Custom CSS in a stylesheet or as an inline style also sets a card's width.
Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport { Button, Card, CardBody, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card style={{ width: '18rem' }}>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>With supporting text below as a natural lead-in to additional content.</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
)
}Text alignment
Text align classes change the text arrangement of a card, in whole or in specific parts.
Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereSpecial title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereSpecial title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport { Button, Card, CardBody, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<>
<Card style={{ width: '18rem' }}>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>
With supporting text below as a natural lead-in to additional content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
<Card className="text-center" style={{ width: '18rem' }}>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>
With supporting text below as a natural lead-in to additional content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
<Card className="text-end" style={{ width: '18rem' }}>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>
With supporting text below as a natural lead-in to additional content.
</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
</>
)
}Navigation
A <Nav> composed inside <CardHeader> adds navigation to a card.
Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport {
Button,
Card,
CardBody,
CardHeader,
CardText,
CardTitle,
Nav,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
return (
<Card className="text-center">
<CardHeader>
<Nav variant="tabs" className="card-header-tabs">
<NavItem>
<NavLink href="#" active>
Active
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#" disabled>
Disabled
</NavLink>
</NavItem>
</Nav>
</CardHeader>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>With supporting text below as a natural lead-in to additional content.</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
)
}Special title treatment
With supporting text below as a natural lead-in to additional content.
Go somewhereimport {
Button,
Card,
CardBody,
CardHeader,
CardText,
CardTitle,
Nav,
NavItem,
NavLink
} from '@chassis-ui/react'
export const Example = () => {
return (
<Card className="text-center">
<CardHeader>
<Nav variant="segments" className="card-header-segments">
<NavItem>
<NavLink href="#" active>
Active
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">Link</NavLink>
</NavItem>
<NavItem>
<NavLink href="#" disabled>
Disabled
</NavLink>
</NavItem>
</Nav>
</CardHeader>
<CardBody>
<CardTitle>Special title treatment</CardTitle>
<CardText>With supporting text below as a natural lead-in to additional content.</CardText>
<Button href="#">Go somewhere</Button>
</CardBody>
</Card>
)
}Images
Beyond a plain image inside a card, images support two more placements: "image caps" at either end of a card, or an overlay behind the card's content.
Image caps
Similar to headers and footers, a card renders top and bottom "image caps" — images at the top or bottom of a card.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Last updated 3 mins ago
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Last updated 3 mins ago
import { Card, CardBody, CardImage, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<>
<Card className="mb-md">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
<CardText>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardText>
</CardBody>
</Card>
<Card className="mb-md">
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
<CardText>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardText>
</CardBody>
<CardImage orientation="bottom" src="https://placehold.co/800x400" alt="" />
</Card>
</>
)
}Image overlays
An image serves as a background with content overlaid on top of it. Depending on the image, additional styles or utilities may be needed for legibility.
import { Card, CardImage, CardImageOverlay, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card className="mb-md bg-black fg-white">
<CardImage src="https://placehold.co/800x400" alt="" />
<CardImageOverlay>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
<CardText>Last updated 3 mins ago</CardText>
</CardImageOverlay>
</Card>
)
}Horizontal
Set direction="row" on <Card> to lay it out side-by-side instead of stacked, or an object
such as direction={{ lg: 'row' }} for a breakpoint-gated switch. Wrap the image and body in
elements with a fraction width (.lg:w-4/12, .lg:w-8/12) to control each side's width, and give
<CardImage> orientation={{ base: 'top', lg: 'start' }} so the image's rounded corners switch
from the top edge to the start edge at the same breakpoint the card switches to a row. At a
breakpoint orientation takes start and end, from sm to xl: top and bottom have a
class at base only.
A Tailwind build of @chassis-ui/css has the classes of direction, and of the gap of
<CardBody>, only with its safelist loaded: see Tailwind.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Last updated 3 mins ago
import { Card, CardBody, CardImage, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card direction={{ lg: 'row' }}>
<div className="lg:w-4/12">
<CardImage
orientation={{ base: 'top', lg: 'start' }}
src="https://placehold.co/800x400"
alt=""
style={{ height: '100%', objectFit: 'cover' }}
/>
</div>
<div className="lg:w-8/12">
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
<CardText>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardText>
</CardBody>
</div>
</Card>
)
}To place the image inside a padded body region instead of flush against the card edge, apply
direction to <CardBody> itself and nest a second <CardBody className="p-0"> for
the text side so it doesn't get double padding.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Last updated 3 mins ago
import { Card, CardBody, CardImage, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<Card>
<CardBody direction={{ lg: 'row' }} gap="md">
<div className="lg:w-4/12">
<CardImage src="https://placehold.co/800x400" alt="" />
</div>
<div className="lg:w-8/12">
<CardBody className="p-0">
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
<CardText className="mb-0">
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardText>
</CardBody>
</div>
</CardBody>
</Card>
)
}Card styles
A card supports several options for customizing its backgrounds, borders, and context.
Context colors
Set color to one of the Chassis context colors, and variant to solid, smooth, or outline
to control the intensity — omit variant for the default (a tinted border and heading, matching
the basic chassis-css style).
primary card title
Some quick example text to build on the card title and make up the bulk of the card's content.
secondary card title
Some quick example text to build on the card title and make up the bulk of the card's content.
neutral card title
Some quick example text to build on the card title and make up the bulk of the card's content.
success card title
Some quick example text to build on the card title and make up the bulk of the card's content.
danger card title
Some quick example text to build on the card title and make up the bulk of the card's content.
warning card title
Some quick example text to build on the card title and make up the bulk of the card's content.
info card title
Some quick example text to build on the card title and make up the bulk of the card's content.
import { Card, CardBody, CardHeader, CardText, CardTitle } from '@chassis-ui/react'
const COLORS = ['primary', 'secondary', 'neutral', 'success', 'danger', 'warning', 'info'] as const
export const Example = () => {
return (
<>
{COLORS.map((color) => (
<Card color={color} className="mb-md" style={{ maxWidth: '18rem' }} key={color}>
<CardHeader>Header</CardHeader>
<CardBody>
<CardTitle>{color} card title</CardTitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
</CardBody>
</Card>
))}
</>
)
}solid card title
Some quick example text to build on the card title and make up the bulk of the card's content.
smooth card title
Some quick example text to build on the card title and make up the bulk of the card's content.
outline card title
Some quick example text to build on the card title and make up the bulk of the card's content.
import { Card, CardBody, CardHeader, CardText, CardTitle } from '@chassis-ui/react'
const VARIANTS = ['solid', 'smooth', 'outline'] as const
export const Example = () => {
return (
<>
{VARIANTS.map((variant) => (
<Card
color="primary"
variant={variant}
className="mb-md"
style={{ maxWidth: '18rem' }}
key={variant}
>
<CardHeader>Header</CardHeader>
<CardBody>
<CardTitle>{variant} card title</CardTitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
</CardBody>
</Card>
))}
</>
)
}Using context to add meaning only provides a visual indication, which isn't conveyed to users of
assistive technologies such as screen readers. Ensure that information denoted by the context is
either obvious from the content itself (e.g. the visible text), or is included through
alternative means, such as additional text hidden with the .visually-hidden class.
Utility styling
For finer-grained control than color/variant provides, background, foreground, and border
utility classes applied via each sub-component's className target individual regions directly.
Primary background
Some quick example text to build on the card title and make up the bulk of the card's content.
Custom text color
Some quick example text to build on the card title and make up the bulk of the card's content.
import { Card, CardBody, CardFooter, CardHeader, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<>
<Card className="border-primary mb-md" style={{ maxWidth: '18rem' }}>
<CardHeader className="primary-bg-evident">Header</CardHeader>
<CardBody className="primary-bg-main">
<CardTitle>Primary background</CardTitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
</CardBody>
<CardFooter className="primary-bg-even">Footer</CardFooter>
</Card>
<Card style={{ maxWidth: '18rem' }}>
<CardHeader className="fg-primary border-primary">Header</CardHeader>
<CardBody className="fg-secondary">
<CardTitle>Custom text color</CardTitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
</CardBody>
<CardFooter className="fg-subtle primary-border-main">Footer</CardFooter>
</Card>
</>
)
}Size variants
Set size to sm or lg to re-scale a card's padding, gaps, and typography together —
omit it for the md default.
Card title
Card subtitle
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereCard title
Card subtitle
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereimport {
Button,
Card,
CardBody,
CardImage,
CardSubtitle,
CardText,
CardTitle
} from '@chassis-ui/react'
export const Example = () => {
return (
<>
<Card size="sm" style={{ width: '16rem' }}>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardSubtitle>Card subtitle</CardSubtitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
<Button href="#" color="primary" className="me-auto">
Go somewhere
</Button>
</CardBody>
</Card>
<Card size="lg" style={{ width: '22rem' }}>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardSubtitle>Card subtitle</CardSubtitle>
<CardText>
Some quick example text to build on the card title and make up the bulk of the card's
content.
</CardText>
<Button href="#" color="primary" className="me-auto">
Go somewhere
</Button>
</CardBody>
</Card>
</>
)
}Card layout
Beyond styling the content within a card, Chassis includes a few options for laying out series of cards.
Card groups
<CardGroup> renders cards as a single, attached element with equal-width and equal-height
columns. <CardGroup> uses a container query to switch from stacked to a row once its container
reaches the sm container breakpoint, so it must be wrapped in an element carrying
.contains-inline to establish that container context.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Last updated 3 mins ago
Card title
This card has supporting text below as a natural lead-in to additional content.
Last updated 3 mins ago
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.
Last updated 3 mins ago
import { Card, CardBody, CardGroup, CardImage, CardText, CardTitle } from '@chassis-ui/react'
export const Example = () => {
return (
<div className="contains-inline">
<CardGroup>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
<CardText>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardText>
</CardBody>
</Card>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This card has supporting text below as a natural lead-in to additional content.
</CardText>
<CardText>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardText>
</CardBody>
</Card>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This card has even longer content than the first to show that equal height
action.
</CardText>
<CardText>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardText>
</CardBody>
</Card>
</CardGroup>
</div>
)
}Card footers line up automatically within a card group.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This card has supporting text below as a natural lead-in to additional content.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.
import {
Card,
CardBody,
CardFooter,
CardGroup,
CardImage,
CardText,
CardTitle
} from '@chassis-ui/react'
export const Example = () => {
return (
<div className="contains-inline">
<CardGroup>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This card has supporting text below as a natural lead-in to additional content.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This card has even longer content than the first to show that equal height
action.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</CardGroup>
</div>
)
}Grid cards
The columns prop of <Grid> controls how many cards share a
row, at every width or per breakpoint. columns={{ base: 1, md: 2 }} lays the cards out on one
column, and splits four cards into two per row from the md breakpoint up.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
import { Card, CardBody, CardFooter, CardImage, CardText, CardTitle, Grid } from '@chassis-ui/react'
export const Example = () => {
return (
<Grid columns={{ base: 1, md: 2 }} gap="md">
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
</Grid>
)
}Changing it to columns={{ base: 1, md: 3 }} wraps the fourth card onto a second row.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
import { Card, CardBody, CardFooter, CardImage, CardText, CardTitle, Grid } from '@chassis-ui/react'
export const Example = () => {
return (
<Grid columns={{ base: 1, md: 3 }} gap="md">
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card>
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
</Grid>
)
}Adding .h-100 to each card gives every card in a row equal height; setting $card-height: 100%
in Sass applies equal heights by default.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This card has supporting text below as a natural lead-in to additional content.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
import { Card, CardBody, CardImage, CardText, CardTitle, Grid } from '@chassis-ui/react'
export const Example = () => {
return (
<Grid columns={{ base: 1, md: 3 }} gap="md">
<div>
<Card className="h-100">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
</Card>
</div>
<div>
<Card className="h-100">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This card has supporting text below as a natural lead-in to additional content.
</CardText>
</CardBody>
</Card>
</div>
<div>
<Card className="h-100">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This card has even longer content than the first to show that equal height
action.
</CardText>
</CardBody>
</Card>
</div>
<div>
<Card className="h-100">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
</Card>
</div>
</Grid>
)
}Card footers line up automatically within an equal-height row, the same as inside a card group.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.
Card title
This card has supporting text below as a natural lead-in to additional content.
Card title
This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.
import { Card, CardBody, CardFooter, CardImage, CardText, CardTitle, Grid } from '@chassis-ui/react'
export const Example = () => {
return (
<Grid columns={{ base: 1, md: 3 }} gap="md">
<div>
<Card className="h-100">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This content is a little bit longer.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card className="h-100">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This card has supporting text below as a natural lead-in to additional content.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
<div>
<Card className="h-100">
<CardImage orientation="top" src="https://placehold.co/800x400" alt="" />
<CardBody>
<CardTitle>Card title</CardTitle>
<CardText>
This is a wider card with supporting text below as a natural lead-in to additional
content. This card has even longer content than the first to show that equal height
action.
</CardText>
</CardBody>
<CardFooter>
<small className="fg-subtle">Last updated 3 mins ago</small>
</CardFooter>
</Card>
</div>
</Grid>
)
}API
Card
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
color? | ContextColor | — |
| Sets the color of the component to one of Chassis context colors. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
direction? | Responsive<FlexDirection> | — |
Switches the card from its default stacked (column) layout to a side-by-side (row) layout.
Give the image and the body a width utility (w-4/12, w-8/12) to control each side's
width. An object sets the direction from a breakpoint up — e.g. { lg: 'row' } to lay the
card out horizontally from lg up while stacking below it. | ||
footer? | ReactNode | — |
Shorthand for a CardFooter, rendered after the image/title/subtitle/text/children block. | ||
image? | ReactNode | — |
Shorthand for a CardImage — pass either a src URL (combine with imageAlt/
imageOrientation) or a fully-formed element — a <CardImage>, <Skeleton>,
<Placeholder>, or anything else — rendered as-is in its place. imageAlt/imageOrientation
only apply to the src form; set them directly on your own element otherwise. For a
horizontal layout or an overlay, omit this and compose CardImage directly as a child
instead. | ||
imageAlt? | string | — |
Accessible alt text for image. Ignored unless image is set. | ||
imageOrientation? | "top" | "bottom" | — |
Orientates image to the top (default) or bottom of the card. | ||
ref? | any | — |
size? | Sizing | — |
| Sets the size of the component to one of Chassis component sizes. | ||
subtitle? | ReactNode | — |
Shorthand for a CardSubtitle, rendered directly after title. | ||
text? | ReactNode | — |
Shorthand for a CardText, rendered after title/subtitle. | ||
title? | ReactNode | — |
Shorthand for a CardTitle. Set alongside subtitle/text (or plain children, e.g. a
Button) to build a standard card without composing CardBody/CardTitle yourself — all
render together inside a single CardBody, in that order. Only takes effect when at least
one of image/title/subtitle/text/footer is set; otherwise children render as-is,
so full manual composition (CardHeader, lists, overlays, nav headers, …) keeps working
unchanged. Mixing shorthand props with a manually-composed children tree isn't supported —
pick one approach per card. | ||
variant? | ContextStyle | — |
Sets the context style of the component. basic (the default) renders with no extra class. | ||
CardBody
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
direction? | Responsive<FlexDirection> | — |
Switches the body from its default stacked (column) layout to a side-by-side (row) layout —
for placing an image beside text within a single padded region. Give the image and the text
a width utility (w-4/12, w-8/12) to control each side's width, and nest another
CardBody (with .p-0) for the text side so it doesn't receive double padding. An object
sets the direction from a breakpoint up: { md: 'row' }. | ||
gap? | { Spacing | 0 } | — |
Spacing between children, mapped to the gap-* utility classes. Overrides the card's default
gap between body children. | ||
ref? | any | — |
CardFooter
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
CardGroup
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
CardHeader
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
CardImage
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
Component used for the root node. Either a string to use a HTML element or a component —
e.g. a framework's own Image component. Its own props (src, fill, priority, etc.)
are type-checked at the call site once passed here. | ||
orientation? | Responsive<CardImageOrientation> | — |
Orientates the image to the top or bottom of the card as an "image cap", or to the start/end
for a horizontal layout. Omit to round all four corners for use inside CardBody. An object
sets the orientation from a breakpoint up — e.g. { base: 'top', lg: 'start' } to switch an
image cap from top to start once the card lays out horizontally. Only start and end
can be set at a breakpoint, from sm to xl: @chassis-ui/css has no class for top or
bottom there, nor for any value at 2xl: such a value renders no class and warns in
development. | ||
ref? | any | — |
CardImageOverlay
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the base component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
CardLink
| Prop | Type | Default |
|---|---|---|
active? | boolean | — |
| Toggle the active state for the component. | ||
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. A string of all className you want applied to the base component. | ||
color? | ContextColor | — |
Sets the link color to one of Chassis context colors, including its interactive
(:hover/:focus/:active/:visited) states. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
disabled? | boolean | — |
| Toggle the disabled state for the component. | ||
href? | string | — |
The href attribute specifies the URL of the page the link goes to. Reaches an <a> or a
component reference (a router link); dropped, with a warning in development, when
component is another element. Declared explicitly here — rather than left to flow through
generically from whatever C is — so consumers that wrap Link (MenuItem, ListItem,
NavLink) can read it with a concrete type regardless of component. | ||
iconLink? | boolean | — |
Aligns a leading or trailing icon with the link text using flexbox, with a gap between
them and an offset underline. Icons need to be passed as children alongside the text.
Named iconLink rather than icon to avoid colliding with components (e.g. MenuItem)
that already have their own, differently-typed icon prop for the icon content itself. | ||
onClick? | MouseEventHandler<HTMLElement> | — |
| Fires on click. | ||
ref? | any | — |
reset? | boolean | — |
| Removes the foreground color override, so the link inherits its color from the nearest ancestor instead of the default link color. | ||
stretched? | boolean | — |
Expands the link's click target to fill its positioned ancestor (the nearest ancestor with
a position other than static). | ||
type? | "button" | "reset" | "submit" | — |
Specifies the type of button. Only applies when component="button". Different browsers may
use different default types for the <button> element, so always specify it explicitly. | ||
CardSubtitle
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
CardText
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |
CardTitle
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
ref? | any | — |