Skip to main content

Flexible container component for grouping related content and actions.

Import

import { Card } from "heroui-solid";

Usage

Become an Acme Creator!

Visit the Acme Creator Hub to sign up today and start earning credits from your fans and followers.

import { CircleDollar } from "gravity-icons-solid"
import { Card, Link } from "heroui-solid"

export function Default() {
  return (
    <Card class="w-[400px]">
      <CircleDollar
        aria-label="Dollar sign icon"
        class="text-accent size-6"
        role="img"
      />
      <Card.Header>
        <Card.Title>Become an Acme Creator!</Card.Title>
        <Card.Description>
          Visit the Acme Creator Hub to sign up today and start earning credits
          from your fans and followers.
        </Card.Description>
      </Card.Header>
      <Card.Footer>
        <Link
          aria-label="Go to Acme Creator Hub (opens in new tab)"
          href="https://heroui.com"
          rel="noopener noreferrer"
          target="_blank"
        >
          Creator Hub
          <Link.Icon aria-hidden="true" />
        </Link>
      </Card.Footer>
    </Card>
  )
}

Anatomy

Import the Card component and access all parts using dot notation.

import { Card } from "heroui-solid";

export default () => (
  <Card>
    <Card.Header>
      <Card.Title />
      <Card.Description />
    </Card.Header>
    <Card.Content />
    <Card.Footer />
  </Card>
);

Variants

Cards come in semantic variants that describe their prominence level rather than specific visual styles. This allows themes to interpret them differently:

Transparent

Minimal prominence with transparent background

Use for less important content or nested cards

Default

Standard card appearance (bg-surface)

The default card variant for most use cases

Secondary

Medium prominence (bg-surface-secondary)

Use to draw moderate attention

Tertiary

Higher prominence (bg-surface-tertiary)

Use for primary or featured content

import { Card } from "heroui-solid"

export function Variants() {
  return (
    <div class="flex flex-col gap-4">
      <Card class="w-[320px]" variant="transparent">
        <Card.Header>
          <Card.Title>Transparent</Card.Title>
          <Card.Description>
            Minimal prominence with transparent background
          </Card.Description>
        </Card.Header>
        <Card.Content>
          <p>Use for less important content or nested cards</p>
        </Card.Content>
      </Card>

      <Card class="w-[320px]" variant="default">
        <Card.Header>
          <Card.Title>Default</Card.Title>
          <Card.Description>
            Standard card appearance (bg-surface)
          </Card.Description>
        </Card.Header>
        <Card.Content>
          <p>The default card variant for most use cases</p>
        </Card.Content>
      </Card>

      <Card class="w-[320px]" variant="secondary">
        <Card.Header>
          <Card.Title>Secondary</Card.Title>
          <Card.Description>
            Medium prominence (bg-surface-secondary)
          </Card.Description>
        </Card.Header>
        <Card.Content>
          <p>Use to draw moderate attention</p>
        </Card.Content>
      </Card>

      <Card class="w-[320px]" variant="tertiary">
        <Card.Header>
          <Card.Title>Tertiary</Card.Title>
          <Card.Description>
            Higher prominence (bg-surface-tertiary)
          </Card.Description>
        </Card.Header>
        <Card.Content>
          <p>Use for primary or featured content</p>
        </Card.Content>
      </Card>
    </div>
  )
}
  • transparent - Minimal prominence, transparent background (great for nested cards)
  • default - Standard card for most use cases
  • secondary - Medium prominence to draw moderate attention
  • tertiary - Higher prominence for important content

Horizontal Layout

Cherries

Become an ACME Creator!

Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam dolor sed amet faucibus etiam.

import { Button, Card, CloseButton } from "heroui-solid"

export function Horizontal() {
  return (
    <Card class="w-full items-stretch md:flex-row">
      <div class="relative h-[120px] w-[120px] shrink-0 overflow-hidden rounded-2xl">
        <img
          alt="Cherries"
          class="pointer-events-none absolute inset-0 h-full w-full scale-125 object-cover select-none"
          loading="lazy"
          src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/cherries.jpeg"
        />
      </div>
      <div class="flex flex-1 flex-col gap-3">
        <Card.Header class="gap-1">
          <Card.Title class="pr-8">Become an ACME Creator!</Card.Title>
          <Card.Description>
            Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam
            dolor sed amet faucibus etiam.
          </Card.Description>
          <CloseButton
            aria-label="Close banner"
            class="absolute top-3 right-3"
          />
        </Card.Header>
        <Card.Footer class="mt-auto flex w-full items-center justify-between gap-3">
          <div class="flex flex-col">
            <span class="text-sm font-medium text-foreground">
              Only 10 spots
            </span>
            <span class="text-xs text-muted">Submission ends Oct 10.</span>
          </div>
          <Button>Apply Now</Button>
        </Card.Footer>
      </div>
    </Card>
  )
}

With Avatar

Indie Hackers community

Indie Hackers

148 members

AI Builders community

AI Builders

362 members

import { Avatar, Card } from "heroui-solid"

export function WithAvatar() {
  return (
    <div class="flex flex-wrap gap-4">
      <Card class="w-[200px] gap-2">
        <img
          alt="Indie Hackers community"
          class="pointer-events-none aspect-square w-14 rounded-2xl object-cover select-none"
          loading="lazy"
          src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/demo1.jpg"
        />
        <Card.Header>
          <Card.Title>Indie Hackers</Card.Title>
          <Card.Description>148 members</Card.Description>
        </Card.Header>
        <Card.Footer class="flex gap-2">
          <Avatar aria-label="Martha's profile picture" class="size-5">
            <Avatar.Image
              alt="Martha's avatar"
              src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/red.jpg"
            />
            <Avatar.Fallback class="text-xs">IH</Avatar.Fallback>
          </Avatar>
          <span class="text-xs">By Martha</span>
        </Card.Footer>
      </Card>

      <Card class="w-[200px] gap-2">
        <img
          alt="AI Builders community"
          class="pointer-events-none aspect-square w-14 rounded-2xl object-cover select-none"
          loading="lazy"
          src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/demo2.jpg"
        />
        <Card.Header>
          <Card.Title>AI Builders</Card.Title>
          <Card.Description>362 members</Card.Description>
        </Card.Header>
        <Card.Footer class="flex gap-2">
          <Avatar aria-label="John's profile picture" class="size-5">
            <Avatar.Image
              alt="John's avatar - blue themed"
              src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg"
            />
            <Avatar.Fallback class="text-xs">B</Avatar.Fallback>
          </Avatar>
          <span class="text-xs">By John</span>
        </Card.Footer>
      </Card>
    </div>
  )
}

With Images

Cherries

Become an ACME Creator!

Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam dolor sed amet faucibus etiam.

PAYMENT

You can now withdraw on crypto

Add your wallet in settings to withdraw

JK

Indie Hackers

148 members

AB

AI Builders

362 members

NEO

Home Robot

Futuristic Robot

Bridging the Future

Today, 6:30 PM

Avocado

Avocado Hackathon

Wed, 4:30 PM

Sound Electro event

Sound Electro | Beyond art

Fri, 8:00 PM

import { CircleDollar } from "gravity-icons-solid"
import { Avatar, Button, Card, CloseButton, Link } from "heroui-solid"

export function WithImages() {
  return (
    <div class="flex w-full items-center justify-center">
      <div class="grid w-full max-w-2xl grid-cols-12 gap-4 p-4">
        {/* Row 1: Large Product Card - Available Soon */}
        <Card class="col-span-12 flex h-auto min-h-[152px] flex-col sm:flex-row">
          <div class="relative h-[140px] w-full shrink-0 overflow-hidden rounded-2xl sm:h-[120px] sm:w-[120px]">
            <img
              alt="Cherries"
              class="pointer-events-none absolute inset-0 h-full w-full scale-125 object-cover select-none"
              loading="lazy"
              src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/cherries.jpeg"
            />
          </div>
          <div class="flex flex-1 flex-col gap-3">
            <Card.Header class="gap-1">
              <Card.Title class="pr-8">Become an ACME Creator!</Card.Title>
              <Card.Description>
                Lorem ipsum dolor sit amet consectetur. Sed arcu donec id
                aliquam dolor sed amet faucibus etiam.
              </Card.Description>
              <CloseButton
                aria-label="Close banner"
                class="absolute top-3 right-3"
              />
            </Card.Header>
            <Card.Footer class="mt-auto flex w-full flex-col items-start gap-3 sm:flex-row sm:items-center sm:justify-between">
              <div class="flex flex-col">
                <span class="text-sm font-medium text-foreground">
                  Only 10 spots
                </span>
                <span class="text-xs text-muted">Submission ends Oct 10.</span>
              </div>
              <Button class="w-full sm:w-auto">Apply Now</Button>
            </Card.Footer>
          </div>
        </Card>

        {/* Row 2 */}
        <div class="col-span-12 grid grid-cols-12 gap-4">
          {/* Left Column */}
          <div class="col-span-12 grid grid-cols-12 gap-4 lg:col-span-6">
            {/* Top Card */}
            <Card class="col-span-12">
              <div class="absolute top-3 right-3 z-10">
                <CloseButton aria-label="Close notification" />
              </div>
              <Card.Header class="gap-3">
                <CircleDollar
                  aria-label="Dollar sign icon"
                  class="text-primary size-8 shrink-0"
                  role="img"
                />
                <div class="flex flex-col gap-1">
                  <span class="text-xs font-medium text-muted uppercase">
                    PAYMENT
                  </span>
                  <Card.Title class="pr-8 text-sm sm:text-base">
                    You can now withdraw on crypto
                  </Card.Title>
                  <Card.Description class="text-xs sm:text-sm">
                    Add your wallet in settings to withdraw
                  </Card.Description>
                </div>
              </Card.Header>
              <Card.Footer>
                <Link
                  aria-label="Go to settings"
                  href="#"
                  rel="noopener noreferrer"
                >
                  Go to settings
                  <Link.Icon aria-hidden="true" />
                </Link>
              </Card.Footer>
            </Card>
            {/* Bottom cards */}
            <div class="col-span-12 grid grid-cols-12 gap-4">
              {/* Left Card */}
              <Card class="col-span-12 gap-2 sm:col-span-6">
                <Card.Header>
                  <Avatar class="size-[56px] rounded-xl">
                    <Avatar.Image
                      alt="Demo 1"
                      src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/demo1.jpg"
                    />
                    <Avatar.Fallback>JK</Avatar.Fallback>
                  </Avatar>
                </Card.Header>
                <Card.Content class="mt-1">
                  <p class="text-sm leading-4 font-medium">Indie Hackers</p>
                  <p class="text-xs text-muted">148 members</p>
                </Card.Content>
                <Card.Footer class="flex items-center gap-2">
                  <Avatar class="size-4">
                    <Avatar.Image
                      alt="John"
                      src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/red.jpg"
                    />
                    <Avatar.Fallback>JK</Avatar.Fallback>
                  </Avatar>
                  <p class="text-xs text-muted">By John</p>
                </Card.Footer>
              </Card>
              {/* Right Card */}
              <Card class="col-span-12 gap-2 sm:col-span-6">
                <Card.Header>
                  <Avatar class="size-[56px] rounded-xl">
                    <Avatar.Image
                      alt="Demo 2"
                      src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/demo2.jpg"
                    />
                    <Avatar.Fallback>AB</Avatar.Fallback>
                  </Avatar>
                </Card.Header>
                <Card.Content class="mt-1">
                  <p class="text-sm leading-4 font-medium">AI Builders</p>
                  <p class="text-xs text-muted">362 members</p>
                </Card.Content>
                <Card.Footer class="flex items-center gap-2">
                  <Avatar class="size-4">
                    <Avatar.Image
                      alt="John"
                      src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg"
                    />
                    <Avatar.Fallback>M</Avatar.Fallback>
                  </Avatar>
                  <p class="text-xs text-muted">By Martha</p>
                </Card.Footer>
              </Card>
            </div>
          </div>
          {/* Right Column */}
          <Card class="col-span-12 min-h-[200px] overflow-hidden rounded-3xl lg:col-span-6">
            {/* Background image */}
            <img
              alt="NEO Home Robot"
              aria-hidden="true"
              class="absolute inset-0 h-full w-full object-cover"
              src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/neo2.jpeg"
            />

            {/* Header */}
            <Card.Header class="z-10 text-white">
              <Card.Title class="text-xs font-semibold tracking-wide text-black/70">
                NEO
              </Card.Title>
              <Card.Description class="text-sm leading-5 font-medium text-black/50">
                Home Robot
              </Card.Description>
            </Card.Header>

            {/* Footer */}
            <Card.Footer class="z-10 mt-auto flex items-center justify-between">
              <div>
                <div class="text-sm font-medium text-black">Available soon</div>
                <div class="text-xs text-black/60">Get notified</div>
              </div>
              <Button class="bg-white text-black" size="sm" variant="tertiary">
                Notify me
              </Button>
            </Card.Footer>
          </Card>
        </div>

        {/* Row 3 */}
        <div class="col-span-12 grid grid-cols-12 gap-4">
          {/* Left Column: Card */}
          <Card class="relative col-span-12 h-[250px] sm:h-[300px] md:col-span-8 md:h-[350px]">
            <img
              alt="NEO Home Robot"
              aria-hidden="true"
              class="absolute inset-0 h-full w-full object-cover"
              src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/neo1.jpeg"
            />

            <Card.Footer class="z-10 mt-auto flex items-end justify-between">
              <div>
                <div class="text-base font-medium text-black sm:text-lg">
                  NEO
                </div>
                <div class="text-xs font-medium text-black/50 sm:text-sm">
                  $499/m
                </div>
              </div>
              <Button class="bg-white text-black" size="sm" variant="tertiary">
                Get now
              </Button>
            </Card.Footer>
          </Card>

          {/* Right Column: Cards Stack */}
          <div class="col-span-12 flex flex-col gap-2 md:col-span-4 md:justify-between md:gap-0 md:py-2">
            {/* 1 */}
            <Card class="flex flex-row gap-3 p-1" variant="transparent">
              <img
                alt="Futuristic Robot"
                class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"
                loading="lazy"
                src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/robot1.jpeg"
              />
              <div class="flex flex-1 flex-col justify-center gap-1">
                <Card.Title class="text-sm">Bridging the Future</Card.Title>
                <Card.Description class="text-xs">
                  Today, 6:30 PM
                </Card.Description>
              </div>
            </Card>
            {/* 2 */}
            <Card class="flex flex-row gap-3 p-1" variant="transparent">
              <img
                alt="Avocado"
                class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"
                loading="lazy"
                src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/avocado.jpeg"
              />
              <div class="flex flex-1 flex-col justify-center gap-1">
                <Card.Title class="text-sm">Avocado Hackathon</Card.Title>
                <Card.Description class="text-xs">
                  Wed, 4:30 PM
                </Card.Description>
              </div>
            </Card>
            {/* 3 */}
            <Card class="flex flex-row gap-3 p-1" variant="transparent">
              <img
                alt="Sound Electro event"
                class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"
                loading="lazy"
                src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/oranges.jpeg"
              />
              <div class="flex flex-1 flex-col justify-center gap-1">
                <Card.Title class="text-sm">
                  Sound Electro | Beyond art
                </Card.Title>
                <Card.Description class="text-xs">
                  Fri, 8:00 PM
                </Card.Description>
              </div>
            </Card>
          </div>
        </div>
      </div>
    </div>
  )
}

With Form

Login

Enter your credentials to access your account

import { Button, Card, Form, Input, Label, Link, TextField } from "heroui-solid"

export function WithForm() {
  const onSubmit = (event: SubmitEvent) => {
    event.preventDefault()
    alert("Form submitted successfully!")
  }

  return (
    <Card class="w-full max-w-md">
      <Card.Header>
        <Card.Title>Login</Card.Title>
        <Card.Description>
          Enter your credentials to access your account
        </Card.Description>
      </Card.Header>
      <Form onSubmit={onSubmit}>
        <Card.Content>
          <div class="flex flex-col gap-4">
            <TextField name="email">
              <Label>Email</Label>
              <Input
                placeholder="email@example.com"
                type="email"
                variant="secondary"
              />
            </TextField>
            <TextField name="password">
              <Label>Password</Label>
              <Input
                placeholder="••••••••"
                type="password"
                variant="secondary"
              />
            </TextField>
          </div>
        </Card.Content>
        <Card.Footer class="mt-4 flex flex-col gap-2">
          <Button fullWidth type="submit">
            Sign In
          </Button>
          <Link class="text-center text-sm" href="#">
            Forgot password?
          </Link>
        </Card.Footer>
      </Form>
    </Card>
  )
}

Accessibility

import { Card } from "heroui-solid";
import { cardVariants } from "heroui-solid";

// Semantic markup
<Card role="article" aria-labelledby="card-title">
  <Card.Header>
    <Card.Title id="card-title">Article Title</Card.Title>
  </Card.Header>
</Card>

// Interactive cards
<a class={cardVariants().base()} href="/details" aria-label="View product details">
  <Card.Title>Product Name</Card.Title>
</a>
  • Surface: Base container surface
  • Avatar: Display user profile images (not ported yet)
  • Form: Form validation and submission handling (not ported yet)

Styling

Component Customization

<Card class="border-2 border-blue-500 bg-gradient-to-r from-blue-50 to-purple-50">
  <Card.Header>
    <Card.Title class="text-blue-900">Custom Styled Card</Card.Title>
    <Card.Description class="text-blue-700">Custom colors applied</Card.Description>
  </Card.Header>
  <Card.Content>
    <p class="text-blue-800">Content with custom styling</p>
  </Card.Content>
</Card>

CSS Variable Overrides

/* Override specific variants */
.card--secondary {
  @apply bg-gradient-to-br from-blue-50 to-purple-50;
}

/* Custom element styles */
.card__title {
  @apply text-xl font-bold;
}

CSS Classes

Card uses BEM naming for predictable styling (View source styles):

Base Classes

  • .card - Base container with padding and border
  • .card__header - Header section container
  • .card__title - Title with base font size and weight
  • .card__description - Muted description text
  • .card__content - Flexible content container
  • .card__footer - Footer with row layout

Variant Classes

  • .card--transparent - Minimal prominence, transparent background
  • .card--default - Standard appearance (default)
  • .card--secondary - Medium prominence
  • .card--tertiary - Higher prominence

API Reference

Card

PropTypeDefaultDescription
variant"transparent" | "default" | "secondary" | "tertiary""default"Semantic variant indicating prominence level
classstring-Additional CSS classes
childrenJSX.Element-Card content
asValidComponent"div"Overrides the default DOM element (Kobalte polymorphic)

Card.Header

PropTypeDefaultDescription
classstring-Additional CSS classes
childrenJSX.Element-Header content

Card.Title

PropTypeDefaultDescription
classstring-Additional CSS classes
childrenJSX.Element-Title content (renders as h3)

Card.Description

PropTypeDefaultDescription
classstring-Additional CSS classes
childrenJSX.Element-Description content (renders as p)

Card.Content

PropTypeDefaultDescription
classstring-Additional CSS classes
childrenJSX.Element-Main content

Card.Footer

PropTypeDefaultDescription
classstring-Additional CSS classes
childrenJSX.Element-Footer content

Differences from HeroUI React

  • Use class instead of className; the element type is overridden with Kobalte's polymorphic as prop instead of React's render prop.
  • The "With Avatar" and "With Images" examples from the official docs are omitted — they rely on Avatar and CloseButton, which aren't ported yet.
  • All parts accept as for custom elements (e.g. <Card.Title as="h2">).

Last updated: 7/19/26, 3:27 AM

HeroUI SolidUnofficial SolidJS port of HeroUI v3, built on Kobalte and @heroui/styles