---
title: "JavaScript Card"
description: "The LemonadeJS Card block for JavaScript: Content card with media, header and footer slots. Contract-verified, framework-agnostic, zero dependencies, with a live example."
source: https://lemonadejs.com/docs/plugins/card/
---

<link rel="stylesheet" href="/v6/card.css">

# JavaScript Card

`@lemonadejs/card` · ✓ 24 contract checks · framework-agnostic · zero dependencies

`<Card />` — a content surface block (LemonadeJS v6)

The classic card sections (header / media / content / actions)
collapsed into one contract-driven block. Every section is a branch:
it only exists in the DOM when its props are set — the media image
when `image` is set, the header when any of avatar/title/subtitle is
set, the action row when `actions` has entries. Children always
render in the content area, after the `content` text.

Two variants through data-variant: '' (elevated — subtle shadow, the
default) and 'outlined' (1px border, no shadow). `clickable` makes
the whole card an interactive surface (hover lift + onclick); action
buttons stop propagation so their clicks never double-fire the card.

## Example

<!--example-->

```js
import { html } from 'lemonadejs';
import Card from '@lemonadejs/card';

const App = (props, { state }) => {
    const status = state('Not saved');
    const actions = [
        { label: 'Share', onclick: () => (status.value = 'Link copied') },
        { label: 'Save', onclick: () => (status.value = 'Saved to your trips') },
    ];

    return html`<div style="display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-start;">
        <div style="width: 300px;">
            <${Card} image="https://picsum.photos/seed/lisbon/600/340"
                title="Lisbon weekend" subtitle="18 to 20 April 2026"
                content="Two nights in Alfama, a day trip to Sintra and pastel de nata on every corner."
                actions="${actions}" />
        </div>
        <div style="width: 300px;">
            <${Card} variant="outlined" clickable title="Porto extension" subtitle="Optional, 1 night"
                content="Click anywhere on this card." onclick="${() => (status.value = 'Porto added to the plan')}" />
            <p>Status: <b>${status}</b></p>
        </div>
    </div>`;
};
```

## Installation

```bash
npm install @lemonadejs/card
```

```js
import Card from '@lemonadejs/card';
import '@lemonadejs/card/style.css';
```

Three deployment forms, one component:

```js
html`<${Card} />`                       // by value (no registration)
setComponents({ Card });               // then <Card /> by name anywhere
createWebComponent(Card);              // <lm-card> in plain HTML/any framework
```

## Props

Every declared prop arrives as a **live state** — pass a value for a snapshot or a
state for a two-way live wire. Attribute strings are coerced to the declared type.

| Prop | Type | Default | Description |
|---|---|---|---|
| `title` | string | `''` | header title line |
| `subtitle` | string | `''` | muted line under the title |
| `image` | string | `''` | media url, top image (object-fit: cover) |
| `imageheight` | number | `180` | media height in px |
| `imagealt` | string | `''` | media image alt text ('' = decorative) |
| `avatar` | string | `''` | small round img beside the header titles |
| `avataralt` | string | `''` | avatar alt text ('' = decorative) |
| `content` | string | `''` | body text (children render after it) |
| `actions` | array | — | CardAction[] — footer buttons, right-aligned |
| `variant` | string | `''` | '' = elevated | outlined |
| `clickable` | boolean | `false` | whole card hover lift + onclick |

## Events

All event names are lowercase (the platform convention — LJS-305 warns otherwise).

- `onclick` — fires when a clickable card is clicked

## Styling

All classes follow the `lm-card-*` convention; visual variants are `data-*`
attributes on the root. Override freely — there is no styling engine to fight.

## Contract

The machine-readable schema ships with the package:

```js
import contract from '@lemonadejs/card/contract.json';
```

`verify.json` carries the conformance proof produced by `verify(Card)`.

Looking for the v5 plugin? See the [archived v5 documentation](/docs/v5/plugins/).