Card

Flexible card component for content containers

Overview

The s-card attribute provides a structured container for content with optional header, body, and footer sections.

Import

/* Full framework (includes all components) */
@import "@shift-css/core";

/* Or import just the card component */
@import "@shift-css/core/components/card";

Note: When importing individual components, you also need @shift-css/core/reset and @shift-css/core/tokens for the base styles and design tokens.

Basic Cards

Card with header, body, and footer

Card with Header

Card body content goes here.

Card Title

Card subtitle text

Using semantic title/subtitle attributes.

<div class="demo-grid">
<article s-card>
  <header s-card-header>
    <strong style="display: block; margin: 0;">Card with Header</strong>
  </header>
  <div s-card-body>
    <p style="margin: 0;">Card body content goes here.</p>
  </div>
  <footer s-card-footer>
    <button s-btn="primary" s-size="sm">Action</button>
  </footer>
</article>
<article s-card>
  <div s-card-body>
    <p s-card-title>Card Title</p>
    <p s-card-subtitle>Card subtitle text</p>
    <p style="margin: 0;">Using semantic title/subtitle attributes.</p>
  </div>
</article>
</div>

Media Card

Card with image

Abstract gradient

Media Card

With image container

Using s-card-media for 16:9 images.

Abstract art

Horizontal Card

Side-by-side layout

Using s-horizontal modifier.

<div class="demo-grid">
<article s-card>
  <div s-card-media>
    <img
      src="https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=400&h=225&fit=crop"
      alt="Abstract gradient"
      width="400"
      height="225"
    />
  </div>
  <div s-card-body>
    <p s-card-title>Media Card</p>
    <p s-card-subtitle>With image container</p>
    <p style="margin: 0;">Using <code>s-card-media</code> for 16:9 images.</p>
  </div>
</article>
<article s-card s-horizontal>
  <div s-card-media>
    <img
      src="https://images.unsplash.com/photo-1557672172-298e090bd0f1?w=200&h=200&fit=crop"
      alt="Abstract art"
      width="200"
      height="200"
    />
  </div>
  <div s-card-body>
    <p s-card-title>Horizontal Card</p>
    <p s-card-subtitle>Side-by-side layout</p>
    <p style="margin: 0;">Using <code>s-horizontal</code> modifier.</p>
  </div>
</article>
</div>

Card Variants

Elevation variants

Flat Card

s-card="flat"

Elevated Card

s-card="elevated"

Outline Card

s-card="outline"

<div class="demo-grid">
<article s-card="flat">
  <div s-card-body>
    <strong style="display: block; margin: 0 0 var(--s-space-2);">Flat Card</strong>
    <p style="margin: 0; font-size: var(--s-text-sm);"><code>s-card="flat"</code></p>
  </div>
</article>
<article s-card="elevated">
  <div s-card-body>
    <strong style="display: block; margin: 0 0 var(--s-space-2);">Elevated Card</strong>
    <p style="margin: 0; font-size: var(--s-text-sm);"><code>s-card="elevated"</code></p>
  </div>
</article>
<article s-card="outline">
  <div s-card-body>
    <strong style="display: block; margin: 0 0 var(--s-space-2);">Outline Card</strong>
    <p style="margin: 0; font-size: var(--s-text-sm);"><code>s-card="outline"</code></p>
  </div>
</article>
</div>

Interactive Card

Hoverable card with lift effect

Hover Me!

s-interactive adds lift on hover.

<article s-card s-interactive>
<div s-card-body>
  <strong style="display: block; margin: 0 0 var(--s-space-2);">Hover Me!</strong>
  <p style="margin: 0; font-size: var(--s-text-sm);"><code>s-interactive</code> adds lift on hover.</p>
</div>
</article>

Card Sections

AttributePurpose
s-cardMain card container
s-card-headerCard header area
s-card-bodyMain content area
s-card-footerFooter with actions
s-card-mediaImage/media container
s-card-titleCard title text
s-card-subtitleSubtitle/description

Examples

Simple Card

<article s-card>
  <div s-card-body>
    <h4>Simple Card</h4>
    <p>Just a body section with content.</p>
  </div>
</article>

Card with All Sections

<article s-card>
  <header s-card-header>
    <h3>Project Update</h3>
  </header>
  <div s-card-body>
    <p>The project is progressing well with all milestones on track.</p>
  </div>
  <footer s-card-footer>
    <button s-btn="ghost" s-size="sm">Cancel</button>
    <button s-btn="primary" s-size="sm">View Details</button>
  </footer>
</article>

Make the entire card clickable:

<article s-card s-link s-interactive>
  <div s-card-body>
    <h4 s-card-title>
      <a href="/details">Clickable Card</a>
    </h4>
    <p>Click anywhere on the card.</p>
  </div>
</article>

Card Layouts

Card Grid

Responsive grid with auto-fitting columns:

<div s-card-grid>
  <article s-card>
    <div s-card-body>Card 1</div>
  </article>
  <article s-card>
    <div s-card-body>Card 2</div>
  </article>
  <article s-card>
    <div s-card-body>Card 3</div>
  </article>
</div>

Card Stack

Vertical list of cards:

<div s-card-stack>
  <article s-card>
    <div s-card-body>Stacked card 1</div>
  </article>
  <article s-card>
    <div s-card-body>Stacked card 2</div>
  </article>
</div>

How It Works

Cards use CSS custom properties for consistent styling:

:where([s-card]) {
  --_card-bg: var(--s-surface-raised);
  --_card-border: var(--s-border-muted);
  --_card-radius: var(--s-radius-xl);
  --_card-padding: var(--s-space-4);

  background-color: var(--_card-bg);
  border: 1px solid var(--_card-border);
  border-radius: var(--_card-radius);
}

:where([s-card-body]) {
  padding: var(--_card-padding);
}

All Attributes

AttributePurposeValues
s-cardCard variant(default), flat, elevated, outline, feature
s-card-headerHeader sectionN/A
s-card-bodyBody sectionN/A
s-card-footerFooter sectionN/A
s-card-mediaMedia containerN/A
s-card-titleTitle elementN/A
s-card-subtitleSubtitle elementN/A
s-interactiveHover lift effectBoolean
s-horizontalHorizontal layoutBoolean
s-linkLink overlayBoolean
s-sizeCard sizesm, lg
s-card-gridGrid containerN/A
s-card-stackStack containerN/A

Customization Examples

Custom Background

<article s-card style="--_card-bg: var(--s-primary-50);">
  <div s-card-body>Tinted card background</div>
</article>

Sharp Corners

[s-card] {
  --_card-radius: 0;
}
Search