rc-card
Design-system-neutral vertical and horizontal card shell with structural slots and parts.
rc-card owns card anatomy and layout affordances, but authors keep native
anchors and buttons for semantics and keyboard access. Themes decide visual
variants through tokens and selectors rather than a variant attribute.
- Package
@rcarls/rc-card- Element
<rc-card>- Native dependency
- Author-provided links and buttons
- State model
- Declarative selected/disabled/interactive hooks
- Main events
- None
- Related
- Theme previews
Installation
- npm
- Yarn
npm install @rcarls/rc-card
yarn add @rcarls/rc-card
import '@rcarls/rc-card/define';
Markup
<rc-card interactive action-target="article-link">
<img slot="media" src="/article-cover.jpg" alt="" />
<h2 slot="title">
<a id="article-link" href="/articles/resilient-interfaces">Resilient interfaces</a>
</h2>
<p>Patterns for preserving native behavior while adding richer interactions.</p>
<button slot="actions" type="button">Save</button>
</rc-card>
The theme-free card provides one rem of body padding and otherwise remains an
undecorated content container. Apply a packaged theme or card tokens when the
composition needs a different spacing scale, shape, elevation, or state layers.
Set orientation="horizontal" to place media in a two-fifths leading column
that spans the card while the remaining structural regions flow through a
three-fifths content column. Cards without media collapse back to one column.
Orientation is presentational and does not set aria-orientation.
Live demo
Structure
Slots cover media, header, title, subtitle, default body, actions,
and footer. Matching parts and reflected has-* attributes let themes adapt
spacing when regions are present or absent.
For shelf/grid layouts, set card tracks through
--rc-card-grid-template-rows and --rc-card-grid-template-columns, then
place each region with its matching --rc-card-*-grid-row and
--rc-card-*-grid-column properties. The demo spans each vertical card across
the parent grid's media, title, body, and action tracks, then uses subgrid on
the hosts to align those regions across cards with different content.
The consumer owns adaptive policy. A size container query cannot write the
orientation attribute, so CSS-driven consumers set the public grid contract
directly:
.shelf {
container: recipe-shelf / inline-size;
}
@container recipe-shelf (inline-size < 26rem) {
.shelf rc-card {
--rc-card-grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
--rc-card-media-grid-row: 1 / -1;
--rc-card-media-grid-column: 1;
--rc-card-title-grid-row: 1;
--rc-card-title-grid-column: 2;
--rc-card-body-grid-row: 2;
--rc-card-body-grid-column: 2;
}
}
Card titles remain author-owned semantic content. The packaged themes normalize
slotted h2 and h3 margins and map those ranks to card-appropriate title
typography. The Material mapping follows the
Material 3 card specification
and Android's semantic
Material 3 type scale.
Action Target
action-target="id" forwards non-interactive surface clicks to a same-root
anchor or button. It is pointer/tap convenience only; keyboard access and
semantics remain on the real target element.
API
Properties
| Property | Markup | Type | Default | Description |
|---|---|---|---|---|
orientation | orientation | RCCardOrientation | 'vertical' | Structural layout direction. |
selected | selected | boolean | false | Declarative selected state for theme styling. |
disabled | disabled | boolean | false | Declarative disabled state. Disables action-target click forwarding. |
interactive | interactive | boolean | false | Visual affordance for cards with an author-provided action target. |
actionTarget | action-target | string | '' | ID of a same-root anchor or button that receives forwarded surface clicks. |
Methods
No public methods are documented in the custom elements manifest.
Events
No custom events are documented in the custom elements manifest.
Slots
| Name | Description |
|---|---|
media | Media region, typically an image or figure. |
header | Header content above title/body. |
title | Primary card title. |
subtitle | Secondary title or metadata. |
(default) | Body content. |
actions | Action row. |
footer | Footer content. |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--rc-card-grid-template-rows | auto auto auto 1fr auto auto | Grid template rows for the host's structural regions. |
--rc-card-grid-template-columns | minmax(0, 1fr) | Grid template columns for the host's structural regions. Horizontal cards default to `minmax(0, 2fr) minmax(0, 3fr)`. |
--rc-card-border | 0 | Card border. |
--rc-card-radius | 0 | Card border radius. |
--rc-card-bg | Canvas | Card background. |
--rc-card-color | CanvasText | Card text color. |
--rc-card-shadow | none | Card box shadow. |
--rc-card-container-bg | transparent | Background of the non-interactive container overlay. |
--rc-card-state-layer-bg | currentColor | State-layer overlay color. |
--rc-card-state-layer-duration | 150ms | State-layer opacity transition duration. |
--rc-card-state-layer-easing | ease | State-layer opacity transition easing. |
--rc-card-hover-state-layer-opacity | 0 | State-layer opacity on hover (interactive cards only). |
--rc-card-pressed-state-layer-opacity | 0 | State-layer opacity on active press (interactive cards only). |
--rc-card-padding-block | Not specified | Shared block-axis padding fallback for regions that don't set their own `*-padding-block` property. Defers to each region's own default (0 for header/title/subtitle/actions/footer, 1rem for body) when unset. |
--rc-card-padding-inline | Not specified | Shared inline-axis padding fallback for regions that don't set their own `*-padding-inline` property. Defers to each region's own default (0 for header/title/subtitle/actions/footer, 1rem for body) when unset. |
--rc-card-media-grid-row | auto | Grid row for the media region. |
--rc-card-media-grid-column | auto | Grid column for the media region. |
--rc-card-header-grid-row | auto | Grid row for the header region. |
--rc-card-header-grid-column | auto | Grid column for the header region. |
--rc-card-header-padding-block | var(--rc-card-padding-block, 0) 0 | Header block-axis padding. |
--rc-card-header-padding-inline | var(--rc-card-padding-inline, 0) | Header inline-axis padding. |
--rc-card-title-grid-row | auto | Grid row for the title region. |
--rc-card-title-grid-column | auto | Grid column for the title region. |
--rc-card-title-padding-block | var(--rc-card-padding-block, 0) 0 | Title block-axis padding. |
--rc-card-title-padding-inline | var(--rc-card-padding-inline, 0) | Title inline-axis padding. |
--rc-card-title-color | inherit | Title text color. |
--rc-card-title-font | inherit | Title font shorthand. |
--rc-card-subtitle-grid-row | auto | Grid row for the subtitle region. |
--rc-card-subtitle-grid-column | auto | Grid column for the subtitle region. |
--rc-card-subtitle-padding-block | 0 | Subtitle block-axis padding. |
--rc-card-subtitle-padding-inline | var(--rc-card-padding-inline, 0) | Subtitle inline-axis padding. |
--rc-card-subtitle-color | inherit | Subtitle text color. |
--rc-card-subtitle-font | inherit | Subtitle font shorthand. |
--rc-card-body-grid-row | auto | Grid row for the body region. |
--rc-card-body-grid-column | auto | Grid column for the body region. |
--rc-card-body-padding-block | var(--rc-card-padding-block, 1rem) | Body block-axis padding. |
--rc-card-body-padding-inline | var(--rc-card-padding-inline, 1rem) | Body inline-axis padding. |
--rc-card-actions-grid-row | auto | Grid row for the actions region. |
--rc-card-actions-grid-column | auto | Grid column for the actions region. |
--rc-card-actions-justify | flex-end | Justify-content for the actions row. |
--rc-card-actions-gap | 0 | Gap between action items. |
--rc-card-actions-padding-block | 0 var(--rc-card-padding-block, 0) | Actions block-axis padding. |
--rc-card-actions-padding-inline | var(--rc-card-padding-inline, 0) | Actions inline-axis padding. |
--rc-card-footer-grid-row | auto | Grid row for the footer region. |
--rc-card-footer-grid-column | auto | Grid column for the footer region. |
--rc-card-footer-padding-block | 0 var(--rc-card-padding-block, 0) | Footer block-axis padding. |
--rc-card-footer-padding-inline | var(--rc-card-padding-inline, 0) | Footer inline-axis padding. |
CSS Parts
| Part | Description |
|---|---|
container | Non-interactive visual container overlay. |
media | Media region wrapper. |
header | Header region wrapper. |
title | Title region wrapper. |
subtitle | Subtitle region wrapper. |
body | Body region wrapper. |
actions | Actions region wrapper. |
footer | Footer region wrapper. |
state-layer | Non-interactive overlay for hover/pressed/ripple effects. |