MDX Notes
Build a flexible Card component system for MDX — variants (elevated, outlined, filled), grid layouts, images, clickable cards, and sub-components.
Cards package content into neat, self-contained boxes. They're everywhere in modern UI — feature grids, team pages, link collections, content previews. In MDX, they let you break out of the plain-text look and present information visually.
Why Cards in MDX?
Markdown gives you headings, paragraphs, and lists. Sometimes that's not enough. You need visual grouping, clear boundaries between items, and a layout that feels polished. Cards do that. They take your docs from "wall of text" to "organized product page."
Component Source Code
Here's the full Card system with sub-components for header, body, footer, image, and grid:
Basic Card Usage in MDX
Here's a simple card with header, body, and footer:
import { Card, CardHeader, CardBody, CardFooter } from '../components/Card';
# Feature Overview
<Card>
<CardHeader>
## Getting Started
</CardHeader>
<CardBody>
Learn how to set up your development environment and create
your first MDX-powered application in under 5 minutes.
</CardBody>
<CardFooter>
**Estimated time:** 5 minutes
</CardFooter>
</Card>Card with Image
Add a hero image at the top:
import { Card, CardImage, CardBody } from '../components/Card';
<Card variant="elevated">
<CardImage
src="/images/tutorial-hero.jpg"
alt="Screenshot of the completed tutorial project"
/>
<CardBody>
## Complete Tutorial
Build a full documentation site from scratch using MDX,
Next.js, and Tailwind CSS.
</CardBody>
</Card>Card Grid Layout
CardGrid arranges cards into a responsive grid — stacks on mobile, fills columns on desktop:
import { Card, CardBody, CardGrid } from '../components/Card';
# Our Features
<CardGrid columns={3}>
<Card variant="outlined">
<CardBody>
### ⚡ Fast
Lightning-fast builds with incremental compilation
and smart caching strategies.
</CardBody>
</Card>
<Card variant="outlined">
<CardBody>
### 🔐 Secure
Built-in security best practices with automatic
vulnerability scanning.
</CardBody>
</Card>
<Card variant="outlined">
<CardBody>
### 📱 Responsive
Mobile-first design that looks great on every
device and screen size.
</CardBody>
</Card>
</CardGrid>Card Variants
Elevated Card (Default)
Uses box shadows for a "floating" look. Shadow deepens on hover:
<Card variant="elevated">
<CardBody>
This card appears to float above the page with a subtle shadow
that intensifies on hover.
</CardBody>
</Card>Outlined Card
Borders instead of shadows. Flatter, more minimal:
<Card variant="outlined">
<CardBody>
This card has a visible border and transparent background.
On hover, the border color transitions to blue.
</CardBody>
</Card>Filled Card
Subtle background color to stand out from the page:
<Card variant="filled">
<CardBody>
This card has a light gray background that differentiates
it from the surrounding content.
</CardBody>
</Card>Clickable Cards (Link Cards)
Pass href to make the whole card a link:
<CardGrid columns={2}>
<Card href="/docs/getting-started" variant="outlined">
<CardBody>
### 📖 Documentation
Full guides and API references for every feature.
</CardBody>
</Card>
<Card href="https://github.com/example/repo" variant="outlined">
<CardBody>
### 🐙 GitHub
View source code, report issues, and contribute to the project.
</CardBody>
</Card>
</CardGrid>Props API Documentation
Card Props
| Prop | Type | Default | Description | ||
|---|---|---|---|---|---|
variant | `'elevated' \ | 'outlined' \ | 'filled'` | 'elevated' | Visual style of the card |
children | ReactNode | required | Card content (use sub-components for structure) | ||
href | string | undefined | Makes the entire card a link | ||
onClick | function | undefined | Click handler for interactive cards | ||
as | ElementType | 'div' | HTML element to render as | ||
className | string | '' | Additional CSS classes |
CardImage Props
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | required | Image source URL |
alt | string | required | Accessible image description |
aspectRatio | string | '16/9' | CSS aspect ratio for the image container |
className | string | '' | Additional CSS classes |
CardGrid Props
| Prop | Type | Default | Description |
|---|---|---|---|
columns | number | 3 | Number of columns at the largest breakpoint |
gap | number | 6 | Tailwind gap unit between cards |
children | ReactNode | required | Card components to arrange |
className | string | '' | Additional CSS classes |
Styling with Plain CSS
If you're not using Tailwind:
/* Card.module.css */
.card {
border-radius: 0.75rem;
overflow: hidden;
transition: all 0.2s ease;
}
.card-elevated {
background: white;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
0 2px 4px -2px rgba(0, 0, 0, 0.1);
border: 1px solid #f3f4f6;
}
.card-elevated:hover {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
0 4px 6px -4px rgba(0, 0, 0, 0.1);
}
.card-outlined {
background: transparent;
border: 2px solid #e5e7eb;
}
.card-outlined:hover {
border-color: #60a5fa;
}
.card-filled {
background: #f9fafb;
border: 1px solid #e5e7eb;
}
.card-clickable {
cursor: pointer;
text-decoration: none;
color: inherit;
}
.card-clickable:hover {
transform: scale(1.02);
}
.card-clickable:active {
transform: scale(0.98);
}
.card-grid {
display: grid;
gap: 1.5rem;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.card-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
.card-grid-3 { grid-template-columns: repeat(3, 1fr); }
.card-grid-4 { grid-template-columns: repeat(4, 1fr); }
}
.card-header {
padding: 1.5rem 1.5rem 0.5rem;
}
.card-body {
padding: 1rem 1.5rem;
}
.card-footer {
padding: 0.5rem 1.5rem 1.5rem;
border-top: 1px solid #f3f4f6;
}
.card-image {
width: 100%;
aspect-ratio: 16/9;
object-fit: cover;
}Responsive Card Patterns
Here's a pattern for feature cards that stack on mobile and sit side-by-side on desktop:
// Responsive card that stacks on mobile, side-by-side on desktop
export function FeatureCard({ icon, title, description, link }) {
return (
<Card variant="outlined" href={link}>
<CardBody>
<div className="flex flex-col sm:flex-row items-start gap-4">
<span className="text-3xl" aria-hidden="true">{icon}</span>
<div>
<h3 className="text-lg font-semibold mb-2">{title}</h3>
<p className="text-gray-600 dark:text-gray-400">{description}</p>
</div>
</div>
</CardBody>
</Card>
);
}Accessibility Notes
A few things to keep in mind:
- Semantic structure — Cards render as
<div>by default but switch to<a>when you passhref. The right element for the job.
- Image alt text —
CardImagerequires analtprop. Write something descriptive, or use an empty string for purely decorative images.
- Focus indicators — Interactive cards should have visible focus styles. Add
focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:outline-nonefor keyboard users.
- External links — When
hrefstarts withhttp, the component addstarget="_blank"andrel="noopener noreferrer"automatically.
- Content hierarchy — Use proper heading levels inside cards. If your cards live under an
<h2>, use<h3>for card titles.
- Color contrast — Make sure text in all card variants meets WCAG AA (4.5:1 for normal text, 3:1 for large text).
Advanced: Animated Card Hover
Add a subtle gradient overlay on hover:
export function AnimatedCard({ children, ...props }) {
return (
<Card
{...props}
className="group relative overflow-hidden"
>
{/* Gradient overlay on hover */}
<div className="absolute inset-0 bg-gradient-to-r from-blue-500/0 to-purple-500/0 group-hover:from-blue-500/5 group-hover:to-purple-500/5 transition-all duration-300" />
<div className="relative z-10">
{children}
</div>
</Card>
);
}Summary
This Card system uses the compound component pattern — Card, CardHeader, CardBody, CardFooter, CardImage all work together but give you full control over structure. Mix and match the pieces, throw them in a grid, make them clickable. One component system, tons of layouts.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Building a Card Component.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this MDX Tutorial topic.
Search Terms
mdx-tutorial, mdx tutorial, mdx, tutorial, components, card, component, building a card component
Related MDX Tutorial Topics