Components

Card

Group related content in a surface with the UiCard component.

UiCard is a surface container. Pick a surface with variant and place content in the #body slot. A surface is static; pointer feedback comes from selectable or link mode.

Add a card

<template>
  <UiCard variant="pane">
    <template #body>
      <h3>Title</h3>
      <p>Card content…</p>
    </template>
  </UiCard>
</template>

Choose a surface

outline draws a border on the default surface, pane a bordered-free panel with a softer contrast, and elevated a shadow. Pick one — they each set the same custom properties, so two on one card means the later class wins.

<template>
  <UiCard variant="outline"><template #body>Outline</template></UiCard>
  <UiCard variant="elevated"><template #body>Elevated</template></UiCard>
  <UiCard variant="pane"><template #body>Pane</template></UiCard>
</template>

None of them react to hover or press on their own. Add selectable for a card the user chooses, or to/href for one that navigates, and the surface answers the pointer: the background steps up, and an elevated card raises its shadow.

Make a card selectable

selectable marks a card the user picks: it lifts on hover and takes a primary border on press or keyboard focus. Add the selected class to hold that border while the choice stands.

<template>
  <UiCard variant="outline" selectable size="sm">
    <template #body>Click-friendly card</template>
  </UiCard>

  <UiCard variant="outline" selectable size="sm" custom-class="selected">
    <template #body>Chosen card</template>
  </UiCard>
</template>

Add a cover image

Pass imageUrl (and optional imageAlt) for a full-bleed cover image at the top of the card, respecting the card radius. Use the #media slot instead if you need custom markup (e.g. a <picture> element).

<template>
  <UiCard variant="outline" image-url="/cover.jpg" image-alt="Cover photo">
    <template #body>
      <h3>Card Title</h3>
      <p>Card content…</p>
    </template>
  </UiCard>
</template>

Setting to or href renders the whole card as a link — the root element switches from div to as (default 'a'), drops the underline and inherits the surrounding text colour, and takes the same hover/press feedback as a selectable card without the lift or the border. External URLs (http(s):, mailto:, tel:, or protocol-relative //) automatically get target="_blank" rel="noopener noreferrer".

<template>
  <UiCard variant="outline" href="https://colorffy.com">
    <template #body>Clickable card</template>
  </UiCard>

  <!-- Internal navigation, e.g. with NuxtLink/RouterLink -->
  <UiCard variant="outline" to="/dashboard" as="NuxtLink">
    <template #body>Internal link card</template>
  </UiCard>
</template>

Props

PropTypeDefaultDescription
idstring | null—DOM id for the card root.
variant'outline' | 'elevated' | 'pane'—Surface style.
size'xs' | 'sm' | 'md'—Card size.
titlestring | null—Optional title.
selectablebooleanfalseAdds card-selectable interactive styling.
imageUrlstring | null—Cover image URL, rendered full-bleed at the top of the card.
imageAltstring | null—Alt text for the cover image (decorative/empty by default).
tostring | object | null—Navigation destination. Activates link mode.
hrefstring | null—Standard href for link mode (e.g. external links). Activates link mode.
asstring | object | null'a'Tag/component rendered in link mode. Ignored unless to/href is set.
customClassstring | string[] | Record<string, boolean> | null—Extra classes.

Slots: #media (cover image area, defaults to the imageUrl/imageAlt image), #header, #body, #footer (and any content placed inside).

CSS variables

Set these on :root, or on any wrapper to restyle only the cards inside it. The outline, elevated, pane and frosted surfaces keep their own background, border and shadow, and the sm / xs sizes their padding. Hover and pressed backgrounds come from the shared state layer.

:root {
  --cffy-card-radius: var(--cffy-radius-xl);
  --cffy-card-padding-inline: var(--cffy-space-24);
  --cffy-card-selected-border-color: var(--cffy-accent-a10);
}
VariableDefaultControls
--cffy-card-bg-color / --cffy-card-color--cffy-surface-a0 / --cffy-on-backgroundBackground and text
--cffy-card-border-width / --cffy-card-border-color--cffy-border-width-sm / transparentBorder
--cffy-card-radius--cffy-shape-container (12px)Corners, including the cover image, header and footer
--cffy-card-shadownoneShadow
--cffy-card-padding-inline / --cffy-card-padding-block--cffy-space-16Header, body and footer padding
--cffy-card-title-font-size / --cffy-card-title-font-weight--cffy-fs-base / --cffy-fw-700Title
--cffy-card-text-color--cffy-muted-a10.card-text paragraphs
--cffy-card-selected-border-color--cffy-primary-a10Selected or focused selectable card
--cffy-card-easing--cffy-ease-emphasizedSelectable and link card transitions
Copyright © 2026