Card
Flexible container for grouping related content and actions. Cards extend the surface system with header, title, description, content, and footer slots plus semantic surface variants.
Import
import { AvCardImports } from '@avesra/angular';Usage
Apply av-card to a container and compose optional header, content, and footer regions.
Become an Acme Creator!
Visit the Acme Creator Hub to sign up today and start earning credits from your fans and followers.
import { Component } from '@angular/core';
import {
AvCardImports,
AvLinkImports,
} from '@avesra/angular';
import { AppIconComponent } from '../../components/app-icon/app-icon.component';
@Component({
selector: 'app-card-basic-demo',
imports: [
AvCardImports,
AvLinkImports,
AppIconComponent,
],
template: `<div av-card class="w-[400px]">
<span class="self-start" role="img" aria-label="Dollar sign icon">
<app-icon icon="solar:dollar-linear" size="24" class="text-foreground" />
</span>
<div av-card-header>
<h3 av-card-title>Become an Acme Creator!</h3>
<p av-card-description>
Visit the Acme Creator Hub to sign up today and start earning credits from your fans and
followers.
</p>
</div>
<div av-card-footer>
<a
av-link
aria-label="Go to Acme Creator Hub (opens in new tab)"
href="https://github.com/"
rel="noopener noreferrer"
target="_blank"
>
Creator Hub
<span av-link-icon></span>
</a>
</div>
</div>`,
})
export class CardBasicDemo {}Anatomy
Import the Card components and compose the layout with av-card, av-card-header, av-card-title, av-card-description, av-card-content, and av-card-footer.
<div av-card>
<div av-card-header>
<h3 av-card-title></h3>
<p av-card-description></p>
</div>
<div av-card-content></div>
<div av-card-footer></div>
</div>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 { Component } from '@angular/core';
import { AvCardImports } from '@avesra/angular';
@Component({
selector: 'app-card-variants-demo',
imports: [AvCardImports],
template: `<div class="flex flex-col gap-4">
<div av-card class="w-[320px]" variant="transparent">
<div av-card-header>
<h3 av-card-title>Transparent</h3>
<p av-card-description>Minimal prominence with transparent background</p>
</div>
<div av-card-content>
<p>Use for less important content or nested cards</p>
</div>
</div>
<div av-card class="w-[320px]" variant="default">
<div av-card-header>
<h3 av-card-title>Default</h3>
<p av-card-description>Standard card appearance (bg-surface)</p>
</div>
<div av-card-content>
<p>The default card variant for most use cases</p>
</div>
</div>
<div av-card class="w-[320px]" variant="secondary">
<div av-card-header>
<h3 av-card-title>Secondary</h3>
<p av-card-description>Medium prominence (bg-surface-secondary)</p>
</div>
<div av-card-content>
<p>Use to draw moderate attention</p>
</div>
</div>
<div av-card class="w-[320px]" variant="tertiary">
<div av-card-header>
<h3 av-card-title>Tertiary</h3>
<p av-card-description>Higher prominence (bg-surface-tertiary)</p>
</div>
<div av-card-content>
<p>Use for primary or featured content</p>
</div>
</div>
</div>`,
})
export class CardVariantsDemo {}transparent— Minimal prominence, transparent background (great for nested cards)default— Standard card for most use cases (surface-secondary)secondary— Medium prominence to draw moderate attention (surface-tertiary)tertiary— Higher prominence for important content (surface-tertiary)
Horizontal Layout

Become an ACME Creator!
Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam dolor sed amet faucibus etiam.
import { Component } from '@angular/core';
import {
AvButtonComponent,
AvCardImports,
AvCloseButtonComponent,
} from '@avesra/angular';
@Component({
selector: 'app-card-horizontal-with-image-demo',
imports: [
AvCardImports,
AvButtonComponent,
AvCloseButtonComponent,
],
template: `<div av-card class="w-full items-stretch md:flex-row">
<div
class="relative h-[140px] w-full shrink-0 overflow-hidden rounded-2xl sm:h-[120px] sm:w-[120px]"
>
<img
alt="Yellow pears"
class="pointer-events-none absolute inset-0 h-full w-full scale-125 object-cover select-none"
loading="lazy"
src="/images/food/food-yellow-pears-pair.png"
/>
</div>
<div class="flex flex-1 flex-col gap-3">
<div av-card-header class="gap-1">
<h3 av-card-title class="pr-8">Become an ACME Creator!</h3>
<p av-card-description>
Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam dolor sed amet
faucibus etiam.
</p>
<button
av-close-button
aria-label="Close banner"
class="absolute top-3 right-3"
></button>
</div>
<div
av-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 av-button class="w-full sm:w-auto">Apply Now</button>
</div>
</div>
</div>`,
})
export class CardHorizontalWithImageDemo {}With Avatar

Indie Hackers
148 members
AI Builders
362 members
import { Component } from '@angular/core';
import {
AvAvatarImports,
AvCardImports,
} from '@avesra/angular';
@Component({
selector: 'app-card-with-avatar-demo',
imports: [
AvCardImports,
AvAvatarImports,
],
template: `<div class="flex flex-wrap gap-4">
<div av-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="/images/objects/object-yellow-mushroom-lamp.png"
/>
<div av-card-header>
<h3 av-card-title>Indie Hackers</h3>
<p av-card-description>148 members</p>
</div>
<div av-card-footer class="flex gap-2">
<span av-avatar class="size-5" aria-label="Martha's profile picture">
<img
av-avatar-image
alt="Martha's avatar"
src="/images/gradients/gradient-pink-magenta.png"
/>
<span av-avatar-fallback class="text-xs">IH</span>
</span>
<span class="text-xs">By Martha</span>
</div>
</div>
<div av-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="/images/avatars/avatar-woman-orange-jacket.png"
/>
<div av-card-header>
<h3 av-card-title>AI Builders</h3>
<p av-card-description>362 members</p>
</div>
<div av-card-footer class="flex gap-2">
<span av-avatar class="size-5" aria-label="John's profile picture">
<img
av-avatar-image
alt="John's avatar - blue themed"
src="/images/gradients/gradient-blue-cyan.png"
/>
<span av-avatar-fallback class="text-xs">B</span>
</span>
<span class="text-xs">By John</span>
</div>
</div>
</div>`,
})
export class CardWithAvatarDemo {}With Images

Become an ACME Creator!
Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam dolor sed amet faucibus etiam.
You can now withdraw on crypto
Add your wallet in settings to withdraw
JKIndie Hackers
148 members
AI Builders
362 members
NEO
Home Robot

Bridging the Future
Today, 6:30 PM

Avocado Hackathon
Wed, 4:30 PM

Sound Electro | Beyond art
Fri, 8:00 PM
import { Component } from '@angular/core';
import {
AvAvatarImports,
AvButtonComponent,
AvCardImports,
AvCloseButtonComponent,
AvLinkImports,
} from '@avesra/angular';
import { AppIconComponent } from '../../components/app-icon/app-icon.component';
@Component({
selector: 'app-card-with-images-demo',
imports: [
AvCardImports,
AvButtonComponent,
AvCloseButtonComponent,
AvLinkImports,
AvAvatarImports,
AppIconComponent,
],
template: `<div class="flex w-full items-center justify-center">
<div class="grid w-full max-w-2xl grid-cols-12 gap-4 p-4">
<div av-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="Yellow pears"
class="pointer-events-none absolute inset-0 h-full w-full scale-125 object-cover select-none"
loading="lazy"
src="/images/food/food-yellow-pears-pair.png"
/>
</div>
<div class="flex flex-1 flex-col gap-3">
<div av-card-header class="gap-1">
<h3 av-card-title class="pr-8">Become an ACME Creator!</h3>
<p av-card-description>
Lorem ipsum dolor sit amet consectetur. Sed arcu donec id aliquam dolor sed amet
faucibus etiam.
</p>
<button
av-close-button
aria-label="Close banner"
class="absolute top-3 right-3"
></button>
</div>
<div
av-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 av-button class="w-full sm:w-auto">Apply Now</button>
</div>
</div>
</div>
<div class="col-span-12 grid grid-cols-12 gap-4">
<div class="col-span-12 grid grid-cols-12 gap-4 lg:col-span-6">
<div av-card class="col-span-12">
<div class="absolute top-3 right-3 z-10">
<button av-close-button aria-label="Close notification"></button>
</div>
<div av-card-header class="flex-row items-start gap-3">
<span role="img" aria-label="Dollar sign icon" class="shrink-0">
<app-icon icon="solar:dollar-linear" size="32" class="text-accent" />
</span>
<div class="flex flex-col gap-1">
<span class="text-xs font-medium text-muted uppercase">PAYMENT</span>
<h3 av-card-title class="pr-8 text-sm sm:text-base">
You can now withdraw on crypto
</h3>
<p av-card-description class="text-xs sm:text-sm">
Add your wallet in settings to withdraw
</p>
</div>
</div>
<div av-card-footer>
<a av-link aria-label="Go to settings" href="#" rel="noopener noreferrer">
Go to settings
<span av-link-icon></span>
</a>
</div>
</div>
<div class="col-span-12 grid grid-cols-12 gap-4">
<div av-card class="col-span-12 gap-2 sm:col-span-6">
<div av-card-header>
<span av-avatar class="size-[56px] rounded-xl">
<img
av-avatar-image
alt="Indie Hackers"
src="/images/objects/object-yellow-mushroom-lamp.png"
/>
<span av-avatar-fallback>JK</span>
</span>
</div>
<div av-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>
</div>
<div av-card-footer class="flex items-center gap-2">
<span av-avatar class="size-4">
<img
av-avatar-image
alt="John"
src="/images/gradients/gradient-pink-magenta.png"
/>
<span av-avatar-fallback>JK</span>
</span>
<p class="text-xs text-muted">By John</p>
</div>
</div>
<div av-card class="col-span-12 gap-2 sm:col-span-6">
<div av-card-header>
<span av-avatar class="size-[56px] rounded-xl">
<img
av-avatar-image
alt="AI Builders"
src="/images/avatars/avatar-woman-orange-jacket.png"
/>
<span av-avatar-fallback>AB</span>
</span>
</div>
<div av-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>
</div>
<div av-card-footer class="flex items-center gap-2">
<span av-avatar class="size-4">
<img
av-avatar-image
alt="John"
src="/images/gradients/gradient-blue-cyan.png"
/>
<span av-avatar-fallback>M</span>
</span>
<p class="text-xs text-muted">By Martha</p>
</div>
</div>
</div>
</div>
<div
av-card
class="col-span-12 min-h-[200px] overflow-hidden rounded-3xl lg:col-span-6"
>
<img
alt="NEO Home Robot"
aria-hidden="true"
class="absolute inset-0 h-full w-full object-cover"
src="/images/characters/character-robot-rear-gold-slit.png"
/>
<div av-card-header class="z-10 text-white">
<h3 av-card-title class="text-xs font-semibold tracking-wide text-black/70">NEO</h3>
<p av-card-description class="text-sm leading-5 font-medium text-black/50">
Home Robot
</p>
</div>
<div av-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 av-button class="bg-white text-black" size="sm" variant="tertiary">
Notify me
</button>
</div>
</div>
</div>
<div class="col-span-12 grid grid-cols-12 gap-4">
<div
av-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="/images/characters/character-robot-front-eyes.png"
/>
<div av-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 av-button class="bg-white text-black" size="sm" variant="tertiary">
Get now
</button>
</div>
</div>
<div
class="col-span-12 flex flex-col gap-2 md:col-span-4 md:justify-between md:gap-0 md:py-2"
>
<div av-card class="flex flex-row gap-3 p-1" variant="transparent">
<img
alt="Astronaut"
class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"
loading="lazy"
src="/images/characters/character-astronaut-white-suit.png"
/>
<div class="flex flex-1 flex-col justify-center gap-1">
<h3 av-card-title class="text-sm">Bridging the Future</h3>
<p av-card-description class="text-xs">Today, 6:30 PM</p>
</div>
</div>
<div av-card class="flex flex-row gap-3 p-1" variant="transparent">
<img
alt="Peaches on ice"
class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"
loading="lazy"
src="/images/food/food-peaches-ice-blue.png"
/>
<div class="flex flex-1 flex-col justify-center gap-1">
<h3 av-card-title class="text-sm">Avocado Hackathon</h3>
<p av-card-description class="text-xs">Wed, 4:30 PM</p>
</div>
</div>
<div av-card class="flex flex-row gap-3 p-1" variant="transparent">
<img
alt="Blood orange"
class="aspect-square h-16 w-16 shrink-0 rounded-xl object-cover select-none sm:h-20 sm:w-20"
loading="lazy"
src="/images/food/food-blood-orange-half.png"
/>
<div class="flex flex-1 flex-col justify-center gap-1">
<h3 av-card-title class="text-sm">Sound Electro | Beyond art</h3>
<p av-card-description class="text-xs">Fri, 8:00 PM</p>
</div>
</div>
</div>
</div>
</div>
</div>`,
})
export class CardWithImagesDemo {}With Form
Login
Enter your credentials to access your account
import { Component } from '@angular/core';
import {
AvButtonComponent,
AvCardImports,
AvFormComponent,
AvInputComponent,
AvLabelComponent,
AvLinkImports,
} from '@avesra/angular';
@Component({
selector: 'app-card-with-form-demo',
imports: [
AvCardImports,
AvFormComponent,
AvLabelComponent,
AvInputComponent,
AvButtonComponent,
AvLinkImports,
],
template: `<div av-card class="w-full max-w-md">
<div av-card-header>
<h3 av-card-title>Login</h3>
<p av-card-description>Enter your credentials to access your account</p>
</div>
<form av-form (submit)="onSubmit($event)">
<div av-card-content>
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-1">
<label av-label for="card-form-email">Email</label>
<input
av-input
full-width
id="card-form-email"
name="email"
type="email"
placeholder="email@example.com"
variant="secondary"
/>
</div>
<div class="flex flex-col gap-1">
<label av-label for="card-form-password">Password</label>
<input
av-input
full-width
id="card-form-password"
name="password"
type="password"
placeholder="••••••••"
variant="secondary"
/>
</div>
</div>
</div>
<div av-card-footer class="mt-4 flex flex-col gap-2">
<button av-button class="w-full" type="submit">Sign In</button>
<a av-link class="text-center text-sm" href="#">Forgot password?</a>
</div>
</form>
</div>`,
})
export class CardWithFormDemo {
onSubmit(event: Event): void {
event.preventDefault();
const form = event.target as HTMLFormElement;
const formData = new FormData(form);
const data: Record<string, string> = {};
formData.forEach((value, key) => {
data[key] = value.toString();
});
alert('Form submitted successfully!');
}
}Styling
Pass Tailwind utilities on the card host, or override BEM classes in @layer components.
CSS Classes
.av-card— Base card container.av-card__header,.av-card__title,.av-card__description— Header region.av-card__content— Main content area.av-card__footer— Footer actions row.av-card--transparent,.av-card--default,.av-card--secondary,.av-card--tertiary— Surface variants
Accessibility
Cards are presentational containers. For interactive cards, use semantic elements (such as <a>) with an aria-label, or add role="article" with aria-labelledby pointing at av-card-title.
API
Card root accepts a variant input; header, title, description, content, and footer parts have no inputs.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'transparent' | 'default' | 'secondary' | 'tertiary' | 'default' | Visual surface variant (div[av-card]). |



