Card
A content container with optional media, actions, horizontal layout, and clickable-overlay support.
Import
import { Card } from "@hyzer-labs/ui"Demo
Card is headless. The dashed outline below is docs scaffolding, added so its box is visible.
padding="none"
<Card padding="none">
<p>padding="none"</p>
</Card>padding="sm"
<Card padding="sm">
<p>padding="sm"</p>
</Card>padding="md"
<Card padding="md">
<p>padding="md"</p>
</Card>padding="lg"
<Card padding="lg">
<p>padding="lg"</p>
</Card>rounded="none"
<Card rounded="none">
<p>rounded="none"</p>
</Card>rounded="sm"
<Card rounded="sm">
<p>rounded="sm"</p>
</Card>rounded="md"
<Card rounded="md">
<p>rounded="md"</p>
</Card>rounded="lg"
<Card rounded="lg">
<p>rounded="lg"</p>
</Card>A card with action buttons in the footer area.
<Card>
<p>A card with action buttons in the footer area.</p>
{#snippet actions()}
<Button size="sm">Primary</Button>
<Button size="sm" variant="ghost" intent="danger">Cancel</Button>
{/snippet}
</Card>Course spotlight
Eighteen wooded holes with tight fairways and big elevation changes.
<Card>
{#snippet media()}
<img src="…" alt="…" />
{/snippet}
<h3>Course spotlight</h3>
<p>Eighteen wooded holes with tight fairways and big elevation changes.</p>
{#snippet actions()}
<Button size="sm">View course</Button>
{/snippet}
</Card>Course spotlight
Eighteen wooded holes with tight fairways and big elevation changes.
<Card mediaPosition="end">
{#snippet media()}
<img src="…" alt="…" />
{/snippet}
<h3>Course spotlight</h3>
<p>Eighteen wooded holes with tight fairways and big elevation changes.</p>
{#snippet actions()}
<Button size="sm">View course</Button>
{/snippet}
</Card>Course spotlight
Eighteen wooded holes with tight fairways and big elevation changes.
<Card horizontal>
{#snippet media()}
<img src="…" alt="…" />
{/snippet}
<h3>Course spotlight</h3>
<p>Eighteen wooded holes with tight fairways and big elevation changes.</p>
{#snippet actions()}
<Button size="sm">View course</Button>
{/snippet}
</Card>Course spotlight
Eighteen wooded holes with tight fairways and big elevation changes.
<Card horizontal mediaPosition="end">
{#snippet media()}
<img src="…" alt="…" />
{/snippet}
<h3>Course spotlight</h3>
<p>Eighteen wooded holes with tight fairways and big elevation changes.</p>
{#snippet actions()}
<Button size="sm">View course</Button>
{/snippet}
</Card>Props
| Name | Type | Default | Note |
|---|---|---|---|
padding | 'none' | 'sm' | 'md' | 'lg' | 'md' | Set 'none' to opt out and control padding entirely from your own class. |
rounded | 'none' | 'sm' | 'md' | 'lg' | 'md' | |
href | string | — | Makes the whole card clickable. |
ariaLabel | string | — | Required when href is set. |
horizontal | boolean | false | |
mediaPosition | 'start' | 'end' | 'start' | |
class | string | — | Merged after the hz-card class. |
media | Snippet | — | |
children | Snippet | — | |
actions | Snippet | — |
Theme hooks
What this component promises your CSS. The reference theme styles exactly these — from @layer hz-theme, so your unlayered rules win. See Styling Components for the how.
Root class: .hz-card
Data attributes
| Hook | Values | Styles |
|---|---|---|
data-padding | 'none' | 'sm' | 'md' | 'lg' | Lands on .hz-card-content, not the root — which is how media bleeds edge-to-edge while text stays inset. Default md. |
data-rounded | 'none' | 'sm' | 'md' | 'lg' | No full rung, unlike the shared Rounded scale. Default md. |
data-horizontal | present when horizontal | Media beside content above 640px. |
data-clickable | present when href is set | The whole card becomes a target; the theme hangs its hover affordances off this together with a treatment class. |
data-media-position | 'start' | 'end' | Mirrors the prop. The effect is DOM order, not CSS order — so reading order and visual order cannot disagree. |
Custom properties
| Hook | Values | Styles |
|---|---|---|
--hz-card-media-size | <length|percentage> — default 40% | The media track in horizontal mode; media fills it. Never declared, so set it yourself on .hz-card or an ancestor. |
Part classes
| Hook | Values | Styles |
|---|---|---|
.hz-card--outlined | opt-in class | A theme treatment, not a prop: pass it via class. Card ships no variant prop because the look is the theme’s call, not the API’s. |
.hz-card--elevated | opt-in class | The shadow treatment. Same deal. |
.hz-card-title | opt-in class | Card never emits this — you bring the heading element at whatever level the page needs, and the class only styles it. Headings aren’t load-bearing for Card the way they are for Modal or Accordion, so this never became API. |
.hz-card-media | child element | The media wrapper. |
.hz-card-content | child element | The padded region. |
.hz-card-body | child element | The default slot wrapper. |
.hz-card-actions | child element | The actions row. |
.hz-card-link | child element | The overlay anchor, present only when clickable. Its own focus ring would be clipped on rounded cards, so the theme draws the ring on .hz-card itself while this anchor holds focus. |
Accessibility
When href is set, the entire card is wrapped in a link, so supply ariaLabel with a descriptive name. Inner interactive elements remain clickable above the overlay via z-index.