Card
A surface for grouping related content. Default, header+footer, image, and stat variants.
Overview
Card is the most versatile layout surface in Byteion — it groups related content and actions into a portable, scannable unit. Every dashboard metric, product listing, settings section, user profile, and modal body is built on cards. Card provides a bordered, rounded, shadowed surface with composable sub-components: Card.Header (title + description), Card.Body (primary content), and Card.Footer (actions). Two variants — elevated (with shadow) and outline (flat border) — let you layer cards without visual conflict.
Why this exists
Without a shared Card primitive, every surface gets inconsistent padding, borders, shadows, and inner element spacing. Some cards use rounded-lg shadow-md bg-white p-6, others use border p-4, and nested cards often clash with the parent surface. Card unifies these into a structured composition where the container manages its own styling and children (Header, Body, Footer) fill the space without hardcoded margins. Every dashboard, settings page, and listing grid benefits from the same consistent card vocabulary.
Mental model
- Card is a surface, not a layout — it provides the background, border, shadow, and padding. It does not manage how inner elements are positioned — use Stack, Grid, or Flex inside Card.Body for layout.
- Header-Body-Footer composition — Header gets a title and optional description. Body gets the primary content (form, table, text). Footer gets actions (buttons). All three share the card's global padding — no redundant margins on children.
- Variants for layering — elevated (default) has a shadow for top-level cards. Outline has a flat border for nested cards inside other surfaces (modals, drawers, other cards).
- Card groups content — it should contain one logical unit: a single metric, one form section, one product listing. For page-level sections, use Section instead.
Card vs Section vs Container
- Card — a bordered, padded surface for grouping related content. Use for dashboard widgets, settings panels, product cards, and modal bodies.
- Section — a full-width vertical spacing primitive for major page blocks. Section has no border, shadow, or padding — it just creates consistent vertical rhythm between content blocks.
- Container — constrains content width and centers it horizontally. Use Container at the page level; use Card inside Container for individual content groupings.
When to use
- Dashboard metric widgets — individual KPI cards in a dashboard grid
- Product and article listings — product cards in ecommerce, article cards in CMS
- Settings sections — grouped settings panels in account and admin pages
- User profile summaries — profile card with avatar, name, role, and actions
- Modal and dialog bodies — card provides the base surface inside modals
- Stat cards and KPI widgets — single-metric display with label, value, and trend
- Form sections — grouped form fields inside a bordered surface
- Empty states — empty state with icon, message, and CTA inside a card
When not to use
- Do not use cards for full-page sections — use Section for vertical page blocks without borders
- Avoid nesting cards more than one level deep — a card inside a card inside a card creates visual noise. Use outline variant for the child card if nesting is unavoidable
- Do not use cards as page layout containers — use Grid or Flex for layout, not Card
- Do not hardcode padding on card children — the card container manages its own padding. Inner elements should be padding-free
- Do not use a card when a simpler element works — a single paragraph with a label does not need a card wrapper
Basic example
A settings card with header, body, and footer. The card manages padding consistently:
Project alpha
Shipping target: April 12
<div class="rounded-xl border border-border bg-card shadow-card">
<div class="divide-y divide-border">
<div class="p-5">
<p class="text-base font-semibold text-foreground">Project alpha</p>
<p class="text-sm text-muted-foreground mt-1">Shipping target: April 12</p>
</div>
<div class="p-5 text-sm text-muted-foreground">
Add a teammate, configure the environment, then deploy.
</div>
<div class="flex items-center justify-end gap-3 p-5">
<button class="...">Skip</button>
<button class="...">Continue</button>
</div>
</div>
</div>
Variants
| Variant | Classes | Best for |
|---|---|---|
| elevated | rounded-xl border border-border bg-card shadow-card | Top-level dashboard cards, settings panels, modal bodies |
| outline | rounded-xl border border-border bg-card (no shadow) | Nested cards, inside modals, inside other surfaces |
Anatomy
- Card container —
rounded-xl border border-border bg-card shadow-cardwith global padding (p-5) - Card.Header — title (
Card.Title) and optional description (Card.Description) in the padded area, often with a bottom divider - Card.Body — primary content area (form, text, table, list) within the card's global padding
- Card.Footer — actions area (buttons, links) at the bottom, right-aligned for standard actions or left-aligned for forms
- Dividers —
divide-y divide-borderbetween header, body, and footer sections
Usage guidelines
- Do not hardcode padding on inner elements — rely on the card's global padding
- Use a header only when the card needs a title or action (don't add an empty header)
- Cards should be composable — a card can contain a table, form, list, or text
- Use elevated (with shadow) for top-level cards; use outline for nested cards
- Keep cards focused on one logical unit — one metric, one form section, one product
- Use
divide-y divide-borderto separate header, body, and footer visually - Right-align actions in the footer (standard) or left-align for form submissions
Do and Don't
Do
- Use cards for content grouping and surfaces
- Keep inner elements padding-free — card manages padding
- Use elevated for top-level, outline for nested
- Compose with Stack, Grid, and other primitives inside
- Use Header-Body-Footer composition consistently
Don't
- Nest cards more than one level deep
- Use cards as page layout containers — use Grid or Flex
- Hardcode padding on card children
- Use cards for page-level sections — use Section instead
- Mix elevated and outline variants inconsistently
Accessibility
- Card is a
<div>or<article>— use<article>when the card represents an independent, self-contained item (product card, blog post preview, user profile) - Interactive cards — if the entire card is clickable, wrap content in an
<a>tag. Do not useonClickon a<div> - Inner interactive elements — buttons, links, and form controls inside the card should be natively focusable. Do not interfere with their focus management
- Headings inside cards — if a card has a title, use the appropriate heading level (
h2,h3) based on the document outline, not the visual size - Card groups — when displaying a list of cards (product grid, dashboard), wrap them in a
<ul>with each card as an<li>for proper list semantics
Customization
Card styling follows Byteion surface tokens: bg-card, border-border, shadow-card. Border radius (rounded-xl) and padding (p-5) can be adjusted via standard Tailwind classes. The variant system (elevated vs outline) controls shadow presence. For custom card types (stat cards, KPI widgets), compose the specialized card using the base Card with additional inner components rather than adding props to the Card component itself.
HTML example
<!-- Elevated card with header, body, footer -->
<div class="rounded-xl border border-border bg-card shadow-card">
<div class="divide-y divide-border">
<div class="p-5">
<p class="text-base font-semibold text-foreground">Profile settings</p>
<p class="text-sm text-muted-foreground mt-1">Update your personal information.</p>
</div>
<div class="p-5 space-y-4">
<div>
<label class="text-sm font-medium text-foreground">Full name</label>
<input type="text" class="mt-1 block w-full rounded-lg border border-border bg-background px-3 py-2 text-sm" value="Alex Rivera" />
</div>
<div>
<label class="text-sm font-medium text-foreground">Email</label>
<input type="email" class="mt-1 block w-full rounded-lg border border-border bg-background px-3 py-2 text-sm" value="alex@company.com" />
</div>
</div>
<div class="flex items-center justify-end gap-3 p-5">
<button class="inline-flex h-9 items-center justify-center rounded-lg border border-border bg-background px-4 text-sm font-medium text-foreground hover:bg-muted/50">Cancel</button>
<button class="inline-flex h-9 items-center justify-center rounded-lg bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/90">Save</button>
</div>
</div>
</div>
<!-- Outline card for nested surfaces -->
<div class="rounded-xl border border-border bg-card">
<div class="p-5">
<p class="text-sm text-muted-foreground">Use outline when this card lives inside another surface.</p>
</div>
</div>
React example
React exports Card, Card.Header, Card.Title, Card.Description, Card.Body, and Card.Footer from @byteion/react. The variant prop controls elevated vs outline:
import { Button, Card } from '@byteion/react';
export default function CardDemo() {
return (
<div className="grid gap-4 md:grid-cols-2">
<Card>
<Card.Header>
<Card.Title>Project alpha</Card.Title>
<Card.Description>Shipping target: April 12</Card.Description>
</Card.Header>
<Card.Body>
Add a teammate, configure the environment, then deploy.
</Card.Body>
<Card.Footer>
<Button variant="ghost">Skip</Button>
<Button>Continue</Button>
</Card.Footer>
</Card>
<Card variant="outline">
<Card.Header>
<Card.Title>Outline card</Card.Title>
<Card.Description>Lighter surface for nested layouts.</Card.Description>
</Card.Header>
<Card.Body>Use when the card lives inside another surface.</Card.Body>
</Card>
</div>
);
}
Vue example
Vue exports Card, CardHeader, CardTitle, CardDescription, CardBody, and CardFooter from @byteion/vue:
<script setup lang="ts">
import { Button, Card, CardHeader, CardTitle, CardDescription, CardBody, CardFooter } from '@byteion/vue';
</script>
<template>
<div class="grid gap-4 md:grid-cols-2">
<Card>
<CardHeader>
<CardTitle>Project alpha</CardTitle>
<CardDescription>Shipping target: April 12</CardDescription>
</CardHeader>
<CardBody>
Add a teammate, configure the environment, then deploy.
</CardBody>
<CardFooter>
<Button variant="ghost">Skip</Button>
<Button>Continue</Button>
</CardFooter>
</Card>
<Card variant="outline">
<CardHeader>
<CardTitle>Outline card</CardTitle>
<CardDescription>Lighter surface for nested layouts.</CardDescription>
</CardHeader>
<CardBody>Use when the card lives inside another surface.</CardBody>
</Card>
</div>
</template>
API Reference
The Card component is a compound set in both @byteion/react and @byteion/vue:
| Component | Props | Description |
|---|---|---|
| Card | variant (elevated, outline) | Root container with global padding, border, and shadow |
| Card.Header | — | Title + description section with bottom divider |
| Card.Title | — | Card heading text |
| Card.Description | — | Supporting text below the title |
| Card.Body | — | Primary content area |
| Card.Footer | — | Actions area with top divider |
Developer tips
- Use
grid gap-4for card grids — CSS Grid with a consistent gap is the most reliable way to lay out cards responsively - Do not hardcode padding on card children — if you need a sub-section inside Card.Body, wrap it in a
<div>with its own padding rather than breaking the card's global padding - Use outline variant inside modals, drawers, and other cards — nested cards without the outline variant create conflicting shadows
- Keep card titles short — 2–4 words that clearly describe the card content. Use Card.Description for additional context
- Test empty card states — cards with minimal content should not look broken. A card with just a Card.Body and no header/footer should still look deliberate
- Test card loading states — when card content is loading, show Skeleton elements inside the card body to reserve space
Common mistakes
- Nesting cards too deeply — a card inside a card inside a card creates visual confusion. Restructure the layout or use outline variant for nested cards
- Using cards as page layout containers — cards are for content grouping. Use Grid or Flex for page layout
- Hardcoding padding on inner elements — adding
p-4to Card.Body content creates double padding and inconsistent spacing - Using cards for everything — not every content group needs a card. A simple paragraph with a heading in a Section may be cleaner
- Inconsistent variant usage — mixing elevated and outline randomly across the same page makes the interface feel inconsistent. Define a clear rule (top-level = elevated, nested = outline)
- Missing interactive card semantics — clickable cards that use
div onClickinstead of<a>lose keyboard activation and screen reader context
Production usage tips
- Test cards in all surfaces — verify Card renders correctly on dashboard grids, settings pages, modals, drawers, and mobile layouts
- Test dark mode and branded themes —
bg-card,border-border,text-card-foregroundadapt automatically - Test card grid responsiveness — verify that cards in a grid reflow correctly from 4 columns to 2 to 1 on smaller screens
- Test card with long content — cards should not overflow or break the layout when body content is long. Use
truncateor controlled height - Test interactive cards (clickable) — verify keyboard activation (Enter), focus style, and screen reader announcement for clickable card wrappers
- Keep React and Vue APIs aligned with the core HTML composition — the compound component structure mirrors the HTML pattern of Header / Body / Footer
Premium examples
Pro patterns available in Byteion Pro:
- Card with hover lift and shadow transition — interactive card that lifts on hover with a smooth shadow transition, suitable for product and article listings
- Card with image header and overlay text — a card with a full-width image in the header area with overlaid title and gradient
- Expandable card with accordion body — a card whose body expands/collapses to show secondary details
- Dashboard stat card with trend sparkline — a compact stat card with label, large value, trend indicator, and mini sparkline chart
- Ecommerce product card with quick-add — product image, name, price, rating, and an "Add to Cart" button in a compact product card
- Admin setting card with permission toggles — a settings card with grouped toggle switches, help text, and a save footer
- ERP summary card with key metrics — a summary card showing total revenue, order count, and average order value in a compact KPI layout
Related components
- Section — vertical spacing between page-level content blocks
- Grid — two-dimensional layout for arranging cards in rows and columns
- Stack — one-dimensional layout for vertical or horizontal card groups
- Stat Card — specialized single-metric card with label, value, and trend
- KPI Widget — large-format metric display for hero dashboard positions
- Accordion — collapsible panels for progressive disclosure
- Modal — dialog overlay that uses Card as its base surface
API Reference
Related components
Runtime events
Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.
HTML / JS events
No HTML runtime events are declared by this adapter.
React callbacks
No React callback events are declared by this adapter.
Vue emits
No Vue emitted events are declared by this adapter.
Remote / AJAX
This component does not implement Byteion JS remote loading. Use normal HTML form submission, framework state, or your application data layer around it.
Unlock Premium Patterns
Get access to copy-paste ready Pro blocks, SaaS templates, and advanced component patterns.
Explore Pro Components