Card
A surface for grouping content, with three variants, edge-to-edge media, concentric radii and whole-card links.
pnpm dlx shadcn@latest add https://hextaui.com/r/card.jsonAdds the component, the HextaUI theme tokens and any HextaUI components it depends on.
Add the theme tokens to your global CSS, if you haven’t yet.
Install the dependencies.
pnpm add @base-ui/react class-variance-authority cnCopy and paste the following code into your project.
components/ui/card.tsx Update the import paths to match your project setup.
Variants
default sits on a hairline ring with a soft shadow, outline drops the fill and shadow, and muted uses a filled surface for quieter sections.
Sizes
size="sm" tightens the spacing, radius and title size together, so a compact card still looks like part of the same family.
Media
An image, video, picture or aspect ratio placed first or last runs edge to edge. The card drops the padding on that side and clips the media to its corners.
Clickable card
Put a <CardLink /> in the title to make the whole card one link. Buttons and other controls inside stay clickable and keep their own focus, like the star here.
Clickable variants
Each variant gets its own hover feedback once it holds a link, and the focus ring wraps the whole card when the link is focused with the keyboard.
Borders
Add border-b to the header or border-t to the footer and the card adds matching padding on the inner side.
Nested
A card inside CardContent derives its radius from the parent’s radius minus the spacing, so the corners stay concentric.
Long content
Unbroken titles, long URLs, emoji and CJK text wrap inside a narrow card instead of pushing it wider.
Semantics
Every part takes a render prop, so a card can be an <article> with a real heading, header and footer.
Rendered as an article
Every part accepts render for real semantics.
Right to left
The action moves to the inline start and the footer follows the reading direction.
A card is not focusable on its own. These keys apply when it holds a <CardLink />.
| Key | Action |
|---|---|
| Tab | Focuses the card link, which draws the focus ring around the whole card, then moves on to each control inside it. |
| Enter | Follows the card link. |
- The link’s accessible name is its own text, so keep
<CardLink />inside the title rather than wrapping the whole card in an anchor. - Controls inside a clickable card are lifted above the link’s hit area, so they stay reachable by pointer and keyboard.
- Use
renderon<CardTitle />to give the title the heading level that fits your page.
Every part renders a <div> by default, accepts its attributes and takes a render prop to swap the element.
| Prop | Type | Default |
|---|---|---|
variant | "default" | "outline" | "muted" | "default" |
sizeScales spacing, radius and title size together. | "default" | "sm" | "default" |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="card" | Target the card in CSS. |
data-variant | The current variant. |
data-size | The current size. |
data-link | Present while the card contains a CardLink. |
--card-spacing | Inner spacing shared by every part. Set by the size. |
--card-radius | Corner radius. Nested cards derive theirs from the parent. |
--card-title-size | Font size used by CardTitle. |
| Prop | Type | Default |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="card-header" | A grid that places CardAction in the top end corner. |
| Prop | Type | Default |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="card-title" | Target the title. |
| Prop | Type | Default |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="card-description" | Target the description. |
| Prop | Type | Default |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="card-action" | Spans the title and description rows, above a CardLink’s hit area. |
| Prop | Type | Default |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="card-content" | Passes the card radius and spacing down to nested cards. |
| Prop | Type | Default |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="card-footer" | Target the footer. |
| Prop | Type | Default |
|---|---|---|
href | string | – |
renderPass your router’s link component here. | ReactElement | (props, state) => ReactElement | <a> |
| Attribute | Description |
|---|---|
data-slot="card-link" | Stretches its hit area over the whole card. |