Card
Groups related content and actions in a surface with clear hierarchy.
Design
Functional preview
Running with stable DS HTML and CSS, without a component JavaScript runtime.
Open the HTML/CSS/JS playground
Interactive Card · HTML/CSS/JS
Rendered with native HTML; the Card itself is the composition’s only button.
Anatomy
Card Title 3
Description text
Body content goes here. This is a flexible slot for any content.
4.ds-card) — surface with border-radius, optional border or shadow depending on variant.2 Content container (
.ds-card__container) — applies inner padding and gap.3 Header (
.ds-card__header) — wrapper for optional title and description.4 Body (
.ds-card__body) — flexible content area.
Default
Card Title
Description or meta information
This is the card body content. It provides additional context or details about the subject of the card.
Outlined
Outlined Card
With a stronger border
Outlined cards use a more visible border to distinguish content sections clearly from the background.
Elevated
Elevated Card
Raised surface
Elevated cards use a raised surface and shadow instead of a border to create visual depth and hierarchy.
Comparison
Default
Subtle border.
Outlined
Stronger border.
Elevated
Raised surface.
Media and interactive
Custom composition
Use the card as a container when the inner content needs to be composed with other components. Header and footer are optional; the body hosts the primary content.
Token mapping
| Property | Token | CSS variable |
|---|---|---|
| background | semantic.surface.default | --ds-surface-default |
| background (elevated variant) | semantic.surface.raised | --ds-surface-raised |
| border (default variant) | semantic.border.subtle | --ds-border-subtle |
| border (outlined variant) | semantic.border.default | --ds-border-default |
| shadow (elevated) | semantic.shadow.card | --ds-shadow-card |
| border-radius | component.card.radius.default | --ds-card-radius-default |
| border-width | component.card.border-width.default | --ds-card-border-width-default |
.ds-card__container padding | component.card.container.padding.default | --ds-card-container-padding-default |
.ds-card__container gap | component.card.container.gap.default | --ds-card-container-gap-default |
.ds-card__header gap | component.card.header.gap.default | --ds-card-header-gap-default |
.ds-card__title typography | component.card.title.{font-size,line-height,font-weight}.default | --ds-card-title-*-default |
.ds-card__description typography | component.card.subtitle.{font-size,line-height,font-weight}.default | --ds-card-subtitle-*-default |
.ds-card__body typography | component.card.body.{font-size,line-height,font-weight}.default | --ds-card-body-*-default |
.ds-card__footer spacing | component.card.footer.gap.default | --ds-card-footer-gap-default |
.ds-card--interactive border | component.card-interactive.border-* | --ds-card-interactive-border-* |
.ds-card--interactive focus ring radius | component.card-interactive.focus-ring.radius.default | --ds-card-interactive-focus-ring-radius-default |
Usage
When to use
- Content, metadata, and actions form a reusable or comparable unit.
- The surface needs to communicate its own grouping and hierarchy.
When not to use
- The content already has enough hierarchy without an additional surface.
- The interactive Card would need nested buttons or links; avoid nested interactive controls.
Implementation
- Status
- Stable
- Distribution
- npm package
Installation
npm install ds-tispnpm add ds-tisyarn add ds-tisbun add ds-tisImports
import 'ds-tis/css'Markup
<article class="ds-card ds-card--outlined">
<div class="ds-card__container">
<header class="ds-card__header">
<h3 class="ds-card__title">Uso da organização</h3>
</header>
<div class="ds-card__body">128 licenças ativas.</div>
</div>
</article>Web implementation contract
CSS classes
| Class | Description |
|---|---|
ds-card | Base card container |
ds-card--default | Default variant with subtle border |
ds-card--outlined | Outlined variant with stronger border |
ds-card--elevated | Elevated variant with box shadow, no border |
ds-card--interactive | Interactive card derived from outlined with hover, focus, and selected states |
ds-card--selected | Selected state for interactive card |
ds-card__media | Full-bleed media slot above the content container |
ds-card__container | Inner container with content padding and gap |
ds-card__header | Card header section |
ds-card__title | Card title text |
ds-card__description | Card description/meta text |
ds-card__body | Card body content area |
ds-card__footer | Optional area for actions or supporting content |
Accessibility
Keyboard interaction
Cards have no keyboard interaction by default. If the card is interactive (clickable), wrap content in an <a> element or add role="link" with tabindex="0" to make it focusable and operable via Enter.
Accessibility
| WCAG criterion | Requirement | Status |
|---|---|---|
| 1.4.11 Non-text Contrast (AA) | Border or shadow must have at least 3:1 contrast against the page background | ✓ |
| 2.5.8 Target Size min (AA) | If the card is clickable, the entire surface must be the click target | ✓ |
<h2>, <h3>) for card titles to maintain proper document outline. If the entire card is clickable, wrap it in an <a> or <button> element, or use a single link inside the card with a clear accessible name.
Output responsibility
Preserve native element semantics, accessible names, keyboard behavior, and visible focus.
Validation evidence
Covered by the stable Storybook, public runtime tests when applicable, keyboard scenarios, responsive checks, and Axe.