EDS 0.x
Components

Card

Media, content, and footer composition for product surfaces.

Examples

Default

Matches the Figma Card anatomy: media, heading + overflow, subtitle, description, badges, and a simple action footer.

Edit the code below — the preview updates live.

Title

Subtitle

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut et massa mi.

Badge

layout maps to Figma footer types: end (Buttons Simple / IconButton), fluid (Buttons Fluid), between (Social).

Fluid actions

Icon action

Social

Without media

Title

Use Card as a content shell when media is optional.

RTL

Wrap the card (or a parent) in dir="rtl" / lang="fa" with Farsi copy. Right-align the demo in the preview (items-start on a full-width RTL flex panel).

عنوان

زیرعنوان

این متن نمونه کارت به زبان فارسی برای بررسی جهت راست‌به‌چپ است.

نشان

API Reference

Card

Root surface. Compose with Card.Media, Card.Body, and Card.Footer.

PropTypeDefaultDescription
childrenReactNodeCard regions
classNamestringExtra class names

Card.Media

PropTypeDefaultDescription
srcstringImage source
altstringempty stringAccessible name; empty when decorative
aspectRatiostring16 / 9CSS aspect-ratio
objectFitcover / contain / fill / nonecoverImage fit

Card.Heading

PropTypeDefaultDescription
childrenReactNodeTitle
actionReactNodeTrailing overflow control
asheading / p / divh3Title element

Card.Footer

PropTypeDefaultDescription
layoutend / fluid / betweenendAction alignment
dividerbooleantrueTop hairline

Also: Card.Body, Card.Subtitle, Card.Description, Card.Badges, Card.Badge, Card.Meta, Card.MetaItem.

Accessibility

WCAG success criteria

CriterionLevelHow Card supports it
1.1.1 Non-text ContentACard.Media renders a native <img> with alt (defaults to "" for decorative). Pass a meaningful alt when the image conveys information.
1.3.1 Info and RelationshipsACard.Heading uses a real heading (h3 by default via as); subtitle/description are <p>; badges and meta are plain text spans.
1.3.2 Meaningful SequenceAColumn flex preserves DOM order (no order reshuffling). Compose media → body → footer so that sequence is the reading order; heading/footer rows follow dir.
1.4.3 Contrast (Minimum)AATitle, subtitle, description, and meta use semantic text tokens on the surface background. Validate on custom Card backgrounds.
1.4.11 Non-text ContrastAAFooter hairline and badge chrome use border / surface tokens. Nested controls (e.g. Button) carry their own non-text contrast.
2.4.3 Focus OrderANo focus management or trapping. Tab order is the DOM: typically heading action, then any body controls, then footer.
2.4.6 Headings and LabelsAACard.Heading defaults to h3; set as so the title fits the page outline.
1.4.1 Use of ColorAConsumer responsibility — Card.Badge is a single informative style; do not restyle color to carry meaning without descriptive text.
2.1.1 KeyboardAConsumer responsibility — Card is not a widget. Nested controls in action / Card.Footer must be keyboard-operable (Button, links).
2.4.7 Focus VisibleAACard root is not focusable. Nested EDS controls (e.g. Button) provide :focus-visible rings — verify they are not clipped by the card’s overflow: clip.

Why it matters

Cards package media, titles, and actions into a dense product surface. When the title is a styled div, the image has no alt, or the whole card is wrapped in a link that also contains buttons, keyboard and screen-reader users get an unpredictable tab order, duplicate activation, or a missing outline of the page. EDS Card stays a layout composition — semantics come from real headings, honest image text alternatives, and properly labeled nested controls.

Keyboard

Card itself is not focusable and does not define a widget keyboard model. Interaction belongs to the controls you compose into it.

Key / actionBehavior
⇥ TabMoves through focusable descendants in DOM order (heading action, then body controls, then footer).
+ ⇥ TabReverse focus order through the same descendants.
↵ Enter / SpaceActivate the focused nested control (e.g. Button) — not the card surface.
⎋ EscNo card-level behavior; menus or dialogs you open from action / footer own dismiss.

Do not make the card root a single giant link when it also contains buttons — that creates nested interactive content and a confusing focus path. Put navigation on one clear control (footer primary, or heading action) instead.

Screen readers & semantics

SurfaceImplementation
RootPlain <div class="eds-card"> — no landmark or role. Add aria-labelledby only if you need a named region for a specific layout.
Card.MediaNative <img>; alt defaults to "" (decorative). Informative art needs a concise alt that does not repeat the heading verbatim.
Card.HeadingTitle element via as (h3 default). Trailing action is a layout slot — pass a real <button> / Button with an accessible name.
Subtitle / desc<p> elements. In typical composition they are announced after the heading and its action.
Card.BadgePresentational <span> with a single informative style. Meaning must be in the words, not a custom color.
Card.MetaItemText plus optional icon wrapped with aria-hidden="true" so icons stay decorative.
Card.FooterLayout-only <div> (data-layout). Children should be labeled controls (Button, links with clear names).

Focus & visuals

ConcernEDS behavior
FocusRoot is not focusable. Nested EDS buttons draw their own :focus-visible rings.
Overflow.eds-card uses overflow: clip for media/radius. Prefer controls with room inside the padding so focus rings are not clipped at the edge.
ContrastText uses --eds-color-text-* on --eds-card-bg / surface tokens. Spot-check partner themes and custom backgrounds.
RTLTitle sits at inline-start; heading action and layout="end" footer pack to inline-end. Farsi demos: dir="rtl" lang="fa" on a wrapping panel.
MotionCard has no motion of its own; nested menus / loaders must respect prefers-reduced-motion.

Build with it

DoDon’t
Pick Card.Heading as so the title fits the page outline (h2 / h3 / …)Style a div as a title and skip a real heading
Pass meaningful alt on informative Card.Media; leave default "" when decorativeRepeat the full heading in alt, or omit alt on meaningful photography
Use real Buttons (with aria-label when icon-only) in action and Card.FooterPut click handlers on non-interactive wrappers inside the card
Keep one clear primary action in the footer (or a single navigational control)Wrap the entire card in a link when nested buttons / overflow menus also exist
Write badge and meta copy that stands alone without colorRestyle Card.Badge so status is only a color, with no text meaning
// Heading level + labeled overflow
<Card.Heading
  as="h2"
  action={
    <Button
      size="sm"
      variant="ghost"
      aria-label="More options"
      iconStart={<Icon name="ellipsis-outline" />}
    />
  }
>
  Equinix Metal server
</Card.Heading>

// Decorative vs informative media
<Card.Media src="/hero.png" alt="" />
<Card.Media src="/rack.png" alt="Four servers in a colo rack" />

Quick test

  1. Outline — In the accessibility tree / headings list, confirm each card title appears at the expected level (as).
  2. Keyboard — Tab through heading action and footer buttons; confirm a visible focus ring and activation with Enter/Space. Confirm the card surface itself is not a tab stop.
  3. Screen reader — Verify the heading, description, and button names are announced; decorative media is skipped; informative alt is read once.
  4. Nested interactives — If you tried a whole-card link plus footer buttons, remove the outer link and re-test focus order.
  5. RTL — Open the RTL example; confirm title and body start on the right, and the heading action plus layout="end" footer sit on the left.
  6. Contrast — Check title/body text and badge borders on the real card background (including dark mode).

On this page