vi-card__title
This is the vi-card__text slot. It carries supporting copy and sits inside vi-card__body.
A contained surface for grouping related content. Commonly used for blog posts, services, team members, or any repeating content unit.
Recent decision: card media is content-driven (no fixed height), and the focus ring uses the canonical interactive.focus role. See Decisions.
Cards are built from slots. Mix and match — you don't need all of them. The only required piece is vi-card on the wrapper.
This is the vi-card__text slot. It carries supporting copy and sits inside vi-card__body.
<article class="vi-card vi-card--raised">
<!-- Optional: image or video at top -->
<div class="vi-card__media">
<img src="..." alt="...">
</div>
<!-- Optional: badges or labels above body -->
<div class="vi-card__header">
<span class="vi-badge vi-badge--brand">New</span>
</div>
<!-- Main content -->
<div class="vi-card__body">
<span class="vi-card__eyebrow">Category</span>
<h3 class="vi-card__title">Card Title</h3>
<p class="vi-card__text">Supporting description copy.</p>
<div class="vi-card__actions">
<button class="vi-btn vi-btn--secondary vi-btn--sm">Learn More</button>
</div>
</div>
<!-- Optional: action buttons pinned to bottom -->
<div class="vi-card__footer">
<button class="vi-btn vi-btn--ghost vi-btn--sm">Cancel</button>
<button class="vi-btn vi-btn--primary vi-btn--sm">Confirm</button>
</div>
</article>
Border only, no shadow. Good on white backgrounds where shadows feel too heavy.
Subtle shadow, no border. Best for cards on subtle/grey page backgrounds.
Strong 2px border. Use for selected states, featured items, or form-like cards.
<article class="vi-card vi-card--flat">...</article> <article class="vi-card vi-card--raised">...</article> <article class="vi-card vi-card--bordered">...</article>
Add vi-card--interactive when the entire card is clickable (e.g. blog post cards, service tiles). Hover to see the lift effect.
<a href="/post" class="vi-card vi-card--raised vi-card--interactive">
<div class="vi-card__body">
<span class="vi-card__eyebrow">Blog Post</span>
<h3 class="vi-card__title">Post Title</h3>
<p class="vi-card__text">Excerpt copy here.</p>
</div>
</a>
You don't need all the slots. A card with just a body is completely valid.
Just a title and text. No media, no footer, no eyebrow needed.
<div class="vi-card vi-card--flat">
<div class="vi-card__body">
<h3 class="vi-card__title">Simple Card</h3>
<p class="vi-card__text">Just title and text.</p>
</div>
</div>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<article class="vi-card vi-card--raised vi-card--interactive">
<?php if ( has_post_thumbnail() ) : ?>
<div class="vi-card__media">
<?php the_post_thumbnail('medium'); ?>
</div>
<?php endif; ?>
<div class="vi-card__body">
<span class="vi-card__eyebrow"><?php the_category(', '); ?></span>
<h3 class="vi-card__title">
<a href="<?php the_permalink(); ?>" style="color:inherit; text-decoration:none;">
<?php the_title(); ?>
</a>
</h3>
<p class="vi-card__text"><?php the_excerpt(); ?></p>
</div>
</article>
<?php endwhile; endif; ?>
| Class | Type | Description |
|---|---|---|
| vi-card | Base | Required wrapper. Sets background, border-radius, overflow, flex column layout. |
| vi-card--flat | Variant | Border only, no shadow. |
| vi-card--raised | Variant | Drop shadow, no border. Default feel. |
| vi-card--bordered | Variant | Strong 2px border. |
| vi-card--interactive | Modifier | Hover lift animation. Use when whole card is clickable. |
| vi-card__media | Slot | Image/video area at top of card. Content-driven — media keeps its intrinsic height. |
| vi-card__header | Slot | Row above body — for badges or labels. |
| vi-card__body | Slot | Main content area. Flex column with gap. |
| vi-card__footer | Slot | Actions row pinned to bottom. Grey background. |
| vi-card__footer--space-between | Slot modifier | Justify footer content to space-between. |
| vi-card__eyebrow | Typography | Small all-caps label above title. |
| vi-card__title | Typography | Card heading. |
| vi-card__text | Typography | Supporting copy. Grows to fill available body space. |
| vi-card__actions | Typography | Button row inside body (above footer). |