Card
The Card component provides a flexible container for displaying content within a card layout. It’s composed from four parts — Root, Image, Title, and Content — and supports various configurations such as sizes, orientations, and the position of the image relative to the content.
Variations
Sizes
The Card component supports three sizes: sm, md, and lg. The size prop does not actually change the size of the card, but rather the padding and border radius.
Orientation
The Card component supports two orientations: vertical and horizontal. The orientation determines how the card’s content is laid out.
Image position
The position prop controls where the image is placed within the card layout. It supports two values: start and end.
States
The Card component supports selected, disabled, and interactive states:
Installation
import { Card } from '@harnessio/ui/components'
return ( <Card.Root orientation="vertical" position="start"> <Card.Image src="/card-image.png" alt="" /> <Card.Title>Card Title</Card.Title> <Card.Content> Card content goes here </Card.Content> </Card.Root>)Anatomy
Card is a compound component: a Card.Root container that you fill with any combination of Card.Image, Card.Title, and Card.Content.
<Card.Root> <Card.Image src="…" alt="…" /> {/* optional */} <Card.Title>Title</Card.Title> {/* optional */} <Card.Content>Body text</Card.Content> {/* optional */}</Card.Root>- Root — a plain
<div>that lays out the card. It picks the firstCard.Imagechild out of the children and renders it as the card’s image, then wraps everything else in an internal content wrapper.size,orientation,position,selected,disabled, andinteractiveare all styling variants applied here. - Image — an
<img>. Passwidth/heightas numbers (rendered as pixels) or CSS strings. Itsaltcomes straight from thealtyou pass. - Title — a heading, rendered as
<h3>by default. Useasto set the correct level for the surrounding document outline (h1–h6). - Content — a
<div>for the card’s body text or other content.
A few things to know about how Root arranges its children:
- Only the first
Card.Imageis treated as the image; any additional images fall into the content wrapper alongside the title and content. - The image always renders before the content wrapper in the DOM. The visual placement (above/below, left/right) is controlled by
orientationandpositionthrough CSS — not by where you putCard.Imagein the source. - All three children are optional — a card can be image-only, title-only, content-only, or any mix.
Best practices
Do
- Keep each card focused on a single subject — one image, one title, one short block of content.
- Set
Card.Title’sasprop so the heading level fits the page’s outline, rather than always leaving it ath3. - Use
orientation/positionfor layout instead of reordering children — the DOM order stays fixed regardless. - Give every meaningful
Card.Imagea descriptivealt, and usealt=""for purely decorative images.
Don’t
- Don’t rely on
selected,disabled, orinteractiveto make the card behave like a control — they’re visual styles only (see the accessibility notes). - Don’t put more than one
Card.Imagein a card expecting both to appear as images — only the first is placed as the image. - Don’t pack long-form content or many actions into a card; it’s a summary surface, not a page.
Content
- Write titles as short, scannable labels (a name or subject), not full sentences.
- Keep content to a sentence or two that supports the title; link out for detail rather than expanding the card.
- Use sentence case for both title and content.
Accessibility
Card is a presentational container. Card.Root renders a plain <div> with no ARIA role, and its variant props change appearance only — they don’t add behavior or semantics.
Labeling
Card.Titlerenders a real heading (<h3>by default). Setasso the level is correct in context, since a wrong heading level disrupts the document outline for screen-reader users.Card.Imageneeds an accessible name: pass a descriptivealtfor informative images, oralt=""to mark it decorative so it’s skipped. If you omitaltentirely, the image has noaltattribute and assistive tech may announce the file name.
Focus & states
- Root, Image, Title, and Content all forward the standard HTML attributes you pass them onto their rendered elements, so you can add
id,aria-*,role, etc. yourself when a card needs richer semantics. - The card itself is not focusable and has no keyboard handling. Any interactivity has to come from focusable elements you place inside it (a link, a button).
Known limitations
interactiveis visual only. It applies a hover/interaction style but doesn’t make the card focusable, doesn’t give it abutton/linkrole, and adds no keyboard handling. If the whole card should be clickable, nest a real interactive element (e.g. a link that covers the card) and manage focus and keyboard activation yourself.selectedanddisableddon’t reach assistive tech. They toggle styling classes but set noaria-selectedoraria-disabled, anddisableddoes not actually prevent interaction with anything inside the card. Convey those states with the appropriate ARIA attributes (and real disabling) on the interactive element, not with the card variant alone.
Properties
Root
The root container for the card.
Prop | Required | Default | Type |
|---|---|---|---|
| orientation | false | 'vertical' | 'vertical' | 'horizontal' |
| position | false | 'start' | 'start' | 'end' |
| size | false | 'md' | 'sm' | 'md' | 'lg' |
| selected | false | false | boolean |
| disabled | false | false | boolean |
| interactive | false | true | boolean |
| className | false | string | |
| wrapperClassname | false | string |
Card.Root also forwards any other HTMLAttributes<HTMLDivElement> (e.g. id, onClick, aria-*) onto the underlying <div>.
Image
The image element for the card.
Prop | Required | Default | Type |
|---|---|---|---|
| src | true | string | |
| alt | false | string | |
| width | false | number | string | |
| height | false | number | string | |
| className | false | string |
Card.Image also forwards any other ImgHTMLAttributes<HTMLImageElement> onto the underlying <img>.
Title
The title element for the card, rendered as a heading.
Prop | Required | Default | Type |
|---|---|---|---|
| as | false | 'h3' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' |
| className | false | string |
Card.Title also forwards any other HTMLAttributes<HTMLHeadingElement> onto the underlying heading.
Content
The content element for the card.
Prop | Required | Default | Type |
|---|---|---|---|
| className | false | string |
Card.Content also forwards any other HTMLAttributes<HTMLDivElement> onto the underlying <div>.