Card Component
A bounded surface using border + border-radius: var(--radius) with 3 internal zones (header p-6, content p-6 pt-0, footer px-6 py-4), nested corner radius formula (inner = outer − padding), and interactive lift via trans…
$ prime install @community/pattern-card-component Projection
Always in _index.xml · the agent never has to ask for this.
CardComponent [pattern] v1.0.0
A bounded surface using border + border-radius: var(--radius) with 3 internal zones (header p-6, content p-6 pt-0, footer px-6 py-4), nested corner radius formula (inner = outer − padding), and interactive lift via transform: translateY(-2px) + box-shadow step-up on hover.
Loaded when retrieval picks the atom as adjacent / supporting.
CardComponent [pattern] v1.0.0
A bounded surface using border + border-radius: var(--radius) with 3 internal zones (header p-6, content p-6 pt-0, footer px-6 py-4), nested corner radius formula (inner = outer − padding), and interactive lift via transform: translateY(-2px) + box-shadow step-up on hover.
Label
Card Component Pattern
Problem
Cards without consistent structure produce misaligned zones, incorrect radius nesting, and hover effects on non-interactive surfaces that mislead users.
Solution
Apply a standard 3-zone structure (header/content/footer) sharing horizontal padding. Enforce the nested-radius rule for inset elements. Only interactive cards get hover lift.
Structure
<div class="card">
<!-- Header zone: p-6 pb-2 -->
<div class="card__header">
<h3 class="card__title">Card Title</h3>
<span class="card__badge">Optional</span>
</div>
<!-- Description (optional) -->
<div class="card__desc">
<p>Supporting description text.</p>
</div>
<!-- Content zone: p-6 pt-0 -->
<div class="card__content">
<!-- main content -->
</div>
<!-- Footer zone: px-6 py-4, border-top -->
<div class="card__footer">
<span class="card__meta">Last updated 2h ago</span>
<button type="button" class="btn btn-sm">Action</button>
</div>
</div>
<!-- Interactive card (clickable) -->
<a href="/item/1" class="card card--interactive">
...
</a>
Css
.card {
background: hsl(var(--surface));
border: 1px solid hsl(var(--border));
border-radius: var(--radius); /* typically 0.5rem / 8px */
}
.card-raised {
background: hsl(var(--surface-raised));
box-shadow: var(--shadow-md);
}
.card__header { display: flex; align-items: center; justify-content: space-between; padding: 1.5rem 1.5rem 0.5rem; }
.card__desc { padding: 0 1.5rem 0.5rem; }
.card__content { padding: 1.5rem; padding-top: 0; }
.card__footer { display: flex; align-items: center; justify-content: space-between;
border-top: 1px solid hsl(var(--border)); padding: 1rem 1.5rem; }
/* Interactive lift */
.card--interactive {
transition: transform 150ms ease, box-shadow 150ms ease;
cursor: pointer;
}
.card--interactive:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.card--interactive:active { transform: translateY(0); box-shadow: var(--shadow-sm); transition-duration: 75ms; }
.card--interactive:focus-visible { outline: 2px solid hsl(var(--accent)); outline-offset: 2px; }
/* Nested corner radius rule: inner = outer - padding */
/* Card outer-radius: 8px, padding: 24px → inner element radius: 0–4px (smaller than card) */
.card .card__inner-badge { border-radius: 4px; } /* less than card's 8px */
.card .card__cover-img {
border-top-left-radius: var(--radius);
border-top-right-radius: var(--radius);
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
Behavior
- NEVER nest a card inside a card — destroys elevation semantics. Use a bordered div instead.
- Non-interactive cards must NOT have hover lift or cursor-pointer.
- Header, content, footer all share horizontal padding: 1.5rem (24px).
- Featured card differentiation: use ONE technique only (accent border-top 3px OR scale(1.03) OR filled bg).
A11y
- Clickable cards rendered as or
- Interactive card gets focus-visible outline: 2px solid accent at outline-offset: 2px.
- Card title in
or
maintaining logical heading hierarchy.
Loaded when retrieval picks the atom as a focal / direct hit.
CardComponent [pattern] v1.0.0
A bounded surface using border + border-radius: var(--radius) with 3 internal zones (header p-6, content p-6 pt-0, footer px-6 py-4), nested corner radius formula (inner = outer − padding), and interactive lift via transform: translateY(-2px) + box-shadow step-up on hover.
Label
Card Component Pattern
Problem
Cards without consistent structure produce misaligned zones, incorrect radius nesting, and hover effects on non-interactive surfaces that mislead users.
Solution
Apply a standard 3-zone structure (header/content/footer) sharing horizontal padding. Enforce the nested-radius rule for inset elements. Only interactive cards get hover lift.
Structure
<div class="card">
<!-- Header zone: p-6 pb-2 -->
<div class="card__header">
<h3 class="card__title">Card Title</h3>
<span class="card__badge">Optional</span>
</div>
<!-- Description (optional) -->
<div class="card__desc">
<p>Supporting description text.</p>
</div>
<!-- Content zone: p-6 pt-0 -->
<div class="card__content">
<!-- main content -->
</div>
<!-- Footer zone: px-6 py-4, border-top -->
<div class="card__footer">
<span class="card__meta">Last updated 2h ago</span>
<button type="button" class="btn btn-sm">Action</button>
</div>
</div>
<!-- Interactive card (clickable) -->
<a href="/item/1" class="card card--interactive">
...
</a>
Css
.card {
background: hsl(var(--surface));
border: 1px solid hsl(var(--border));
border-radius: var(--radius); /* typically 0.5rem / 8px */
}
.card-raised {
background: hsl(var(--surface-raised));
box-shadow: var(--shadow-md);
}
.card__header { display: flex; align-items: center; justify-content: space-between; padding: 1.5rem 1.5rem 0.5rem; }
.card__desc { padding: 0 1.5rem 0.5rem; }
.card__content { padding: 1.5rem; padding-top: 0; }
.card__footer { display: flex; align-items: center; justify-content: space-between;
border-top: 1px solid hsl(var(--border)); padding: 1rem 1.5rem; }
/* Interactive lift */
.card--interactive {
transition: transform 150ms ease, box-shadow 150ms ease;
cursor: pointer;
}
.card--interactive:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.card--interactive:active { transform: translateY(0); box-shadow: var(--shadow-sm); transition-duration: 75ms; }
.card--interactive:focus-visible { outline: 2px solid hsl(var(--accent)); outline-offset: 2px; }
/* Nested corner radius rule: inner = outer - padding */
/* Card outer-radius: 8px, padding: 24px → inner element radius: 0–4px (smaller than card) */
.card .card__inner-badge { border-radius: 4px; } /* less than card's 8px */
.card .card__cover-img {
border-top-left-radius: var(--radius);
border-top-right-radius: var(--radius);
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
Behavior
- NEVER nest a card inside a card — destroys elevation semantics. Use a bordered div instead.
- Non-interactive cards must NOT have hover lift or cursor-pointer.
- Header, content, footer all share horizontal padding: 1.5rem (24px).
- Featured card differentiation: use ONE technique only (accent border-top 3px OR scale(1.03) OR filled bg).
A11y
- Clickable cards rendered as or
- Interactive card gets focus-visible outline: 2px solid accent at outline-offset: 2px.
- Card title in
or
maintaining logical heading hierarchy.
Label
Card Component Pattern
Problem
Cards without consistent structure produce misaligned zones, incorrect radius nesting, and hover effects on non-interactive surfaces that mislead users.
Solution
Apply a standard 3-zone structure (header/content/footer) sharing horizontal padding. Enforce the nested-radius rule for inset elements. Only interactive cards get hover lift.
Structure
<div class="card">
<!-- Header zone: p-6 pb-2 -->
<div class="card__header">
<h3 class="card__title">Card Title</h3>
<span class="card__badge">Optional</span>
</div>
<!-- Description (optional) -->
<div class="card__desc">
<p>Supporting description text.</p>
</div>
<!-- Content zone: p-6 pt-0 -->
<div class="card__content">
<!-- main content -->
</div>
<!-- Footer zone: px-6 py-4, border-top -->
<div class="card__footer">
<span class="card__meta">Last updated 2h ago</span>
<button type="button" class="btn btn-sm">Action</button>
</div>
</div>
<!-- Interactive card (clickable) -->
<a href="/item/1" class="card card--interactive">
...
</a>
Css
.card {
background: hsl(var(--surface));
border: 1px solid hsl(var(--border));
border-radius: var(--radius); /* typically 0.5rem / 8px */
}
.card-raised {
background: hsl(var(--surface-raised));
box-shadow: var(--shadow-md);
}
.card__header { display: flex; align-items: center; justify-content: space-between; padding: 1.5rem 1.5rem 0.5rem; }
.card__desc { padding: 0 1.5rem 0.5rem; }
.card__content { padding: 1.5rem; padding-top: 0; }
.card__footer { display: flex; align-items: center; justify-content: space-between;
border-top: 1px solid hsl(var(--border)); padding: 1rem 1.5rem; }
/* Interactive lift */
.card--interactive {
transition: transform 150ms ease, box-shadow 150ms ease;
cursor: pointer;
}
.card--interactive:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.card--interactive:active { transform: translateY(0); box-shadow: var(--shadow-sm); transition-duration: 75ms; }
.card--interactive:focus-visible { outline: 2px solid hsl(var(--accent)); outline-offset: 2px; }
/* Nested corner radius rule: inner = outer - padding */
/* Card outer-radius: 8px, padding: 24px → inner element radius: 0–4px (smaller than card) */
.card .card__inner-badge { border-radius: 4px; } /* less than card's 8px */
.card .card__cover-img {
border-top-left-radius: var(--radius);
border-top-right-radius: var(--radius);
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
Behavior
- NEVER nest a card inside a card — destroys elevation semantics. Use a bordered div instead.
- Non-interactive cards must NOT have hover lift or cursor-pointer.
- Header, content, footer all share horizontal padding: 1.5rem (24px).
- Featured card differentiation: use ONE technique only (accent border-top 3px OR scale(1.03) OR filled bg).
A11y
- Clickable cards rendered as or
- Interactive card gets focus-visible outline: 2px solid accent at outline-offset: 2px.
- Card title in
or
maintaining logical heading hierarchy.
Source
prime-system/examples/frontend-design/primes/compiled/@community/pattern-card-component/atom.yaml