Card
A frame around content that belongs together, such as one case in a list of cases. The card is a container, not a component with behaviour: the content decides what the user can do.
How to use it
Section titled “How to use it”Housing benefit application
Sent 4 March. Case number 2026-0481.
ApprovedNursery place application
We need a birth certificate before we can process the application.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/tokens/tokens.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/card/card.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/badge/badge.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/src/components/css/button/button.css"><!-- Or everything in one file: https://cdn.jsdelivr.net/npm/@lo-tek/interfaces@0.36.0/dist/lotek.css --><div class="lt-card"><h3 class="lt-card__title">Housing benefit application</h3><p>Sent 4 March. Case number 2026-0481.</p><span class="lt-badge" data-color="success">Approved</span></div>
<div class="lt-card" data-variant="filled"><h3 class="lt-card__title">Nursery place application</h3><p>We need a birth certificate before we can process the application.</p><button class="lt-button" data-variant="secondary">Upload attachment</button></div>import "@lo-tek/interfaces/tokens.css"import "@lo-tek/interfaces/card.css"import "@lo-tek/interfaces/badge.css"import "@lo-tek/interfaces/button.css"lt is used in two ways, and which one depends on whether you create the element or find it.
If you create the markup, spread the attributes in. That is the way in React, Astro and anything else that renders:
import { lt } from "@lo-tek/interfaces/react"
<div {...lt.card({ variant: "outline" })}> <h3 className={lt.card.title}>Application 2024/1187</h3> <p>In progress.</p></div>The import is from /react here, since the block is JSX. From there the keys are className and htmlFor. In Astro and anything else without React, import @lo-tek/interfaces and you get class and for.
If you have the element in a variable, set them on it with setAttributes. That is the way without JSX, whether you just created the element or found it in a page the server sent:
import { lt } from "@lo-tek/interfaces"
const card = document.createElement("a")card.href = `/case/${caseFile.id}`
lt.setAttributes(card, lt.card({ interactive: true }))lt.card.title gives the class for the heading. See Type-safe use.
data-variant | Used for |
|---|---|
| (omitted) | Outline on the page surface. The default. |
filled | Muted surface, when the card should stand out from white without a border |
The whole card as a link
Section titled “The whole card as a link”<a class="lt-card" data-interactive href="#"><h3 class="lt-card__title">See the whole case</h3><p>All documents, messages and decisions in one place.</p></a>data-interactive gives hover and a focus indicator, but makes nothing clickable on its own. The element has to be an <a> or a <button>. A <div> with a click listener can neither be reached with the keyboard nor be announced as something to press.
If the card has several actions, the whole card should not be a link. The buttons then end up inside a link, and the user cannot press them without navigating. Make one clear link in the heading instead.
Classes you can style
Section titled “Classes you can style”| Class | What it is |
|---|---|
.lt-card | The card itself. The variant comes from data-variant. |
.lt-card__title | The heading inside the card |
| Variable | Default |
|---|---|
--lt-card-padding | var(--lt-spacing-4) |
--lt-card-radius | var(--lt-spacing-2) |
An example. A card that carries a whole section can take more space than one in a list:
Default
The spacing that comes with the package.
Roomy
Same markup, one more class.
<div class="lt-card"><h3 class="lt-heading" data-size="s">Default</h3><p class="lt-paragraph">The spacing that comes with the package.</p></div>
<div class="lt-card roomy-card"><h3 class="lt-heading" data-size="s">Roomy</h3><p class="lt-paragraph">Same markup, one more class.</p></div>.roomy-card {--lt-card-padding: var(--lt-spacing-6);}See Customising for how the variables and the layer work.
Accessibility
Section titled “Accessibility”- The heading in the card should be a real heading element, at the right level for the page. The class sets the size, weight and line height, not the level.
- If the cards are a list, mark them up as a list with
<ul>and<li>. The screen reader then says how many there are and where in the list the user is. - Do not hide important information behind hover. It does not exist on a touch screen.
- The order in the markup is the order the keyboard follows. Moving something visually with CSS does not move focus.