Card
A content card, outline or filled, plain, numbered, illustrated, linked or large, for product surfaces and base.org sections.
Card is a content tile: a numbered step, an illustrated reason, a large lead
claim or a linked article. Product surfaces and base.org sections use the same
component at different sizes and variants. It is a compound component: the card provides the surface, and the
slots Card.Number, Card.Icon, Card.Title, Card.Description,
Card.Meta, Card.Media and Card.Footer place the content. With an href
the whole card is one link. A card stretches to fill its
cell in a Card Group, with the text pinned to the
bottom. The slots are also named exports (CardTitle, CardNumber, and so
on); use those
in a React Server Component, where the Card.Title properties of the client
module are not available.
import { Card } from '@base-org/bds-web/product/card';
<Card>
<Card.Number>01</Card.Number>
<Card.Title>Deposit</Card.Title>
<Card.Description>A customer deposits supported stablecoins in your app.</Card.Description>
</Card>;Variants
Each card is shown on its own here; Card Group lays several out as a section grid.
Outline
The default (variant="outline"): a 12px-radius surface with a hairline border, 16px of padding (24px from
md), a title and body copy. The title uses the Product title-2 step and
the copy body. These sizes and the padding are today's values; the base.org
sizes follow once design settles them.
Deposit
A customer deposits supported stablecoins in your app.
<Card>
<Card.Title>Deposit</Card.Title>
<Card.Description>A customer deposits supported stablecoins in your app.</Card.Description>
</Card>Numbered
Add a Card.Number and it sits top-left in brand blue, 24px above the text.
The text is pinned to the bottom, so a card that is taller than its content
leaves the gap between the number and the text.
01
Deposit
A customer deposits supported stablecoins in your app.
<Card>
<Card.Number>01</Card.Number>
<Card.Title>Deposit</Card.Title>
<Card.Description>A customer deposits supported stablecoins in your app.</Card.Description>
</Card>With illustration
Put a feature icon in Card.Icon and it
takes the number's place: top-left at 64px, 24px above the text. Move it with
position, below. The card passes its hover and in-view state to the
illustration, so it plays without an isHovered prop.
Grow and retain assets on your platform
Give customers additional utility for supported balances, and a way to access liquidity without selling.
<Card>
<Card.Icon><GenerateRevenueIcon /></Card.Icon>
<Card.Title>Grow and retain assets on your platform</Card.Title>
<Card.Description>Give customers additional utility for supported balances, and a way to access liquidity without selling.</Card.Description>
</Card>Illustration position
Card.Icon takes a position: top-left (the default),
top-right, or bottom-right (the default on a large card). With
bottom-right the text moves to the top and the illustration takes the spare
height below it, with at least 40px between them. The position applies
wherever Card.Icon sits in the markup.
Grow assets
More to do with balances.
Scale up
Earn from stablecoin balances.
Stand out
Offer yield and borrowing.
<Card>
<Card.Icon position="top-left"><GenerateRevenueIcon /></Card.Icon>
<Card.Title>Grow assets</Card.Title>
<Card.Description>More to do with balances.</Card.Description>
</Card>
<Card>
<Card.Icon position="top-right"><LiquidityIcon /></Card.Icon>
<Card.Title>Scale up</Card.Title>
<Card.Description>Earn from stablecoin balances.</Card.Description>
</Card>
<Card>
<Card.Icon position="bottom-right"><EcosystemIcon /></Card.Icon>
<Card.Title>Stand out</Card.Title>
<Card.Description>Offer yield and borrowing.</Card.Description>
</Card>| Position | Use for |
|---|---|
top-left | The default, in the number's place. |
top-right | A card whose illustration should read after the title. |
bottom-right | The default on a large card; any card with the text first. |
Large
size="lg" is the large card that leads a Why Base section: a
display-size title, body copy, and the illustration bottom-right by default. It is at
least 520px tall from md.
Built on the trust of Coinbase
Base is built by Coinbase, with the security and compliance practices of a public company.
<Card size="lg">
<Card.Title highlight="Coinbase">Built on the trust of Coinbase</Card.Title>
<Card.Description>Base is built by Coinbase, with the security and compliance practices of a public company.</Card.Description>
<Card.Icon><CoinbaseTrustIcon /></Card.Icon>
</Card>| Size | Use for |
|---|---|
default | A card in a section grid: plain, numbered or illustrated. |
lg | The first, larger card of a Why Base section: a display-size title, at least 520px tall from md, and more padding. |
Filled
variant="filled" is a borderless gray tile for dense grids and carousels,
where a border on every card would add noise. The surface is bds-gray-5 (a
faint white wash in dark mode) and clips its content to the 12px corners. The
padding is 20px at the sides, 16px at the top and 20px at the bottom. The
variant changes only the surface and padding: the slots keep the type steps
of the card's size, so a filled card reads the same as an outline one. A
large filled card keeps the large layout on the gray surface.
Base Builder Grants
Retroactive grants for builders shipping onchain apps on Base.
May 1, 2025
<Card variant="filled">
<Card.Title>Base Builder Grants</Card.Title>
<Card.Description>Retroactive grants for builders shipping onchain apps on Base.</Card.Description>
<Card.Meta>May 1, 2025</Card.Meta>
</Card>| Variant | Use for |
|---|---|
outline | The default: section grids where each card needs its own edge. |
filled | Cards in a carousel or a dense grid, where borders on every card would add noise. The blog post card below is one example. |
Linked card
Give the card an href and it renders a single link, an a, in place of the
div. target and rel pass through. The surface darkens while hovered
(bds-gray-5 on an outline card, bds-gray-10 on a filled one) and shows the
focus ring on keyboard focus. The link's accessible name is all of its text,
so keep the content short.
<Card href="/docs/product/card">
<Card.Title>Deposit</Card.Title>
<Card.Description>A customer deposits supported stablecoins in your app.</Card.Description>
</Card>Blog post
One use of a filled, linked card is the base.org blog post card, as in the
home page's Latest on Base carousel and the /blog grid: a bleeding 2:1 cover,
a title, a description and a date in Card.Meta. The base.org type steps and
the clamping come from className on the slots, not from the variant. The
! makes the brand step win over the slot's own Product step. Mark a draft
with a Badge placed over the cover; Card.Media with
bleed is positioned, so the badge can sit at its corner.
<Card variant="filled" href="/blog/post">
<Card.Media bleed className="aspect-2/1 bg-bds-blue-60">
<img src="/images/cover.webp" alt="" className="size-full object-cover" />
<Badge variant="label" className="absolute top-3 left-3">Draft</Badge>
</Card.Media>
<Card.Title className="truncate text-brand-headline!">Base Builder Grants</Card.Title>
<Card.Description className="line-clamp-3 text-brand-body!">
Retroactive grants for builders shipping onchain apps on Base.
</Card.Description>
<Card.Meta className="text-brand-label!">
<time dateTime="2025-05-01">May 1, 2025</time>
</Card.Meta>
</Card>The number and the illustration are slots, not sizes: a card is numbered or illustrated by what you put in it, and the two sit in the same place.
Slots
Highlight
Card.Title takes a highlight: the first match of that substring in a string
title is coloured brand blue.
Built for everyone
Anyone can build on Base, and anyone can use what gets built.
<CardTitle highlight="for everyone">Built for everyone</CardTitle>Meta
Card.Meta is a small, light gray line (bds-gray-40) under the
description, such as a date or a read time. Wrap a date in a time element.
Deposit
A customer deposits supported stablecoins in your app.
2 min read
<Card>
<Card.Title>Deposit</Card.Title>
<Card.Description>A customer deposits supported stablecoins in your app.</Card.Description>
<Card.Meta>2 min read</Card.Meta>
</Card>Bleed
Card.Media with bleed runs edge to edge across the top of the card: it
cancels the card's padding at the sides and the top, takes the card's top
corners, and moves to the top wherever it sits in the markup. Set the aspect
ratio on the media, such as aspect-2/1 for a blog cover.

Tokenized stocks
Trade US equities onchain, 24 hours a day.
<Card>
<Card.Media bleed className="aspect-2/1 bg-bds-blue-60">
<img src="/images/..." alt="" />
</Card.Media>
<Card.Title>Tokenized stocks</Card.Title>
<Card.Description>Trade US equities onchain, 24 hours a day.</Card.Description>
</Card>Media and footer
Card.Media is a clipped, rounded area for an image or an asset
illustration. Card.Footer is a row for actions under the text, such as a
Button.
Tokenized stocks
Trade US equities onchain, 24 hours a day.
<Card>
<Card.Media>
<img src="/images/..." alt="" />
</Card.Media>
<Card.Title>Tokenized stocks</Card.Title>
<Card.Description>Trade US equities onchain, 24 hours a day.</Card.Description>
<Card.Footer>
<Button size="sm" variant="secondary" arrow>Learn More</Button>
</Card.Footer>
</Card>When to use
Use Card for content tiles: numbered steps or use cases, illustrated reasons, a large lead claim, or a linked article.
Use something else when:
- The card shows one headline number. Put a Stat in the Card instead of the slots.
- The card shows a metric with a chart. Use Metric Card.
- The card holds more than one action. Leave the card without an
hrefand put each action inCard.Footeras a Button; a linked card cannot contain other links or buttons. - The action is a short label rather than a tile of content. Use a Button or Link.
Usage
Do
Keep one idea per card: a short title and one or two sentences. Let the illustration or number carry the rest.
Don't
Mix numbered and illustrated tiles in the same grid, or put both a
Card.Number and a Card.Icon in one card.
Do
Make the whole card one link with href when the card leads to one page,
such as a blog post.
Don't
Put a Button or a Link inside a linked card, or mix outline and filled cards in the same grid.
- Put
Card.Numberfirst and the text after it; the text is pinned to the bottom. Place the illustration withposition, not the markup order. - Let Card Group set the card size. Use
md:row-span-2andmd:col-span-2on the card for the tall or wide cell, not a height on the card. - In dark mode the card surface is dark gray (
bds-gray-2), so it lifts off the page; it needs no extra classes. - Put a bleeding
Card.Mediafirst; it moves to the top anyway, and the reading order then matches what is on screen.
Props
Card
| Prop | Type | Default |
|---|---|---|
hrefMakes the whole card one link: it renders an `a` with a hover state and a focus ring. | Typestring | Default— |
isDisabledWhether the link is disabled. | Typeboolean | Default— |
size`default` is a card whose text sits at the bottom, with an optional | Type"default" | "lg" | Defaultdefault |
targetThe target window for the link. See | TypeHTMLAttributeAnchorTarget | Default— |
variant`outline` is a bordered surface. `filled` is a borderless gray tile for | Type"outline" | "filled" | Defaultoutline |
Card.Icon
| Prop | Type | Default |
|---|---|---|
positionWhere the illustration sits. Defaults to `top-left` on a `default` card | Type"top-left" | "top-right" | "bottom-right" | Default— |
Card.Title
| Prop | Type | Default |
|---|---|---|
highlightA substring of the title to colour brand blue. Only applies to a string title. | Typestring | Default— |
Card.Media
| Prop | Type | Default |
|---|---|---|
bleedRuns the media edge to edge across the top of the card, cancelling the | Typeboolean | Defaultfalse |
Card.Number, Card.Description and Card.Meta take the props of a p,
and Card.Footer the props of a div; none adds props of its own.
Each slot reads the card's size; Card.Media with bleed also reads the
variant to cancel the matching padding.
Accessibility
Card.Title renders an h3, so a section's cards sit under its h2 heading.
The illustration in Card.Icon is decorative and hidden from assistive
technology, so the title and description must carry the meaning on their own.
Without an href the card is not interactive and has no hover state beyond
playing the illustration. Interactive content inside it, such as a Button in
Card.Footer, keeps its own focus ring and keyboard behaviour.
With an href the card is a React Aria Link: one a in the tab order that
opens with Enter, with its text as the accessible name and a focus ring on
keyboard focus. Do not nest other interactive elements in it. Give the cover
image an empty alt when the title already says what the post is, and put a
draft Badge inside the link so it is read with the title.