Components & Buttons
Components
Interactive buttons, button groups, loaders, and keycaps. Buttons extend %surface and %padding-text, providing tactile hover states, focus outlines, and active feedback.
| Name | Description |
|---|---|
button |
Zero-class interactive button element. |
a.btn |
Anchor styled identically to a button. |
.btn-primary |
Primary action button filled with accent color. |
.btn-secondary |
Secondary button with subtle surface background. |
.btn-outline |
Outlined button with hairline border. |
.btn-destructive |
Destructive action button using error red. |
.btn-ghost |
Ghost button transparent until hover. |
.btn-icon |
Square icon action button. |
.btn-group |
Segmented inline button group with shared borders. |
.loader |
Rotating circular spinner with accent glow. |
Alert Banners
components-feedback
Contextual feedback notifications with status colors and left accent borders.
| Name | Description |
|---|---|
.alert |
Container banner using interface typography and status tinting. |
.alert.success |
Success alert themed with green status color. |
.alert.warning |
Warning alert themed with orange status color. |
.alert.error |
Error alert themed with red status color. |
.alert.info |
Informational alert themed with blue status color. |
Card Component
components-layout
In 1991, Edward Tufte published “Envisioning Information” and introduced the concept of “small multiples”—the idea that human brains excel at comparing information when it’s presented in identical visual containers. Show someone seven weather forecasts in seven different layouts, and they’ll struggle. Show them seven identical cards with different data, and patterns emerge instantly. The structure disappears, the content shines.
But here’s the catch: small multiples only work when they’re truly identical. One card with 16px padding, another with 20px, a third with 18px—your brain registers the inconsistency before it processes the content. This component solves that problem by providing a single source of truth for card structure. Every card gets the same padding, the same borders, the same rhythm. Build one card or build a hundred—they’ll feel like family.
The Swiss designers understood this in the 1950s. Josef Müller-Brockmann’s concert posters used rigid grids not to constrain creativity, but to amplify it. When the structure is invisible, when it just works, your content can breathe. That’s what .card does—it handles the boring consistency so you can focus on making something beautiful.
Future Improvements
- Elevation variants (flat, raised, floating) with shadow scales
- Interactive hover states for clickable cards with smooth transitions
- Horizontal card layout variant for image + content side-by-side
- Dark mode shadow adjustments for better depth perception
- Optional card image hero with object-fit controls
| Name | Description |
|---|---|
.card |
Structured container with surface elevation, hairline borders, and rhythm padding. |
.card-header |
Header area for card title and metadata. |
.card-body |
Main content body with automatic vertical rhythm. |
.card-footer |
Bottom action bar for links and buttons. |
.card.clickable |
Interactive clickable card variant with hover lift. |
.card-grid |
Responsive grid container specifically designed for card multiples. |
Basic card structure
<article class="card">
<header class="card-header">
<h3>Card Title</h3>
</header>
<div class="card-body">
<p>Card content with automatic spacing and rhythm.</p>
</div>
<footer class="card-footer">
<a href="#">Read more →</a>
</footer>
</article>
Live
Card Title
Card content with automatic spacing and rhythm.
Cards in grid layout (3-column responsive)
<div class="grid">
<article class="card col-4 col-sm-12">
<div class="card-body">
<h3>Feature One</h3>
<p>Description...</p>
</div>
</article>
<article class="card col-4 col-sm-12">...</article>
<article class="card col-4 col-sm-12">...</article>
</div>
Live
Feature One
Description…
Clickable card (entire card is a link)
<a href="/article" class="card card-clickable">
<div class="card-body">
<h3>Article Title</h3>
<p>Preview text that entices you to click...</p>
</div>
</a>
Live
Customizing card via CSS variables
.card.custom {
--card-border-color: var(--color-accent);
--card-padding: var(--size-lg);
--card-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
author Francis Fontaine · since 0.11.0 · see {class} .grid – Often used to layout multiple cards in columns · see {variable} —base – Controls internal spacing rhythm · see {class} .prose – Can be used inside card-body for rich content · link https://en.wikipedia.org/wiki/Edward_Tufte Information Design Pioneer · link https://www.nngroup.com/articles/cards-component/ NN/g Cards Research
Clickable Card Variant
components-layout
Sometimes your entire card should be clickable—a blog post preview, a product listing, a project showcase. This variant ensures proper hover states, focus indicators, and cursor feedback while maintaining the card’s structural integrity.
The subtle lift on hover (2px translateY) and enhanced shadow create the illusion of depth—like the card is rising toward you. It’s a tactile metaphor for “this is interactive.” The focus-visible outline ensures keyboard users can see exactly where they are.
Accessibility note: When using clickable cards, ensure the link text is descriptive. “Read more” alone isn’t enough—screen readers need context. Use “Read more about [article title]” or aria-label.
Accessible clickable card
<a href="/article/typography-history" class="card card-clickable"
aria-label="Read full article about Typography History">
<div class="card-body">
<h3>Typography History</h3>
<p>The evolution of type from Gutenberg to now...</p>
</div>
<div class="card-footer">
Read more →
</div>
</a>
Live
since 0.11.0 · see {class} .card – Base component · see {element} a – Applied to anchor tag wrapping card content
Callout Blocks
components-layout
Obsidian-style callout boxes with icons, titles, and collapsible folding.
| Name | Description |
|---|---|
.callout |
Container callout card with raised shadow and ring border. |
.callout-title |
Header title for callout. |
.callout-content |
Body content within callout. |
details.callout |
Collapsible fold callout using native HTML details. |
Comments
components
Threaded discussion list with author names, timestamps, and quotes.
| Name | Description |
|---|---|
#comments |
Root comments container. |
.comment |
Single comment card with surface background and elevation. |
.comment-header |
Author, date, and status metadata bar. |
.comment-content |
Indented comment message body. |
since 0.11.0
Alert Action Links
components-feedback
Actions within alerts (links, buttons) should be visually distinct but not overwhelming. This provides subtle styling that inherits the alert’s color.
| Name | Description |
|---|---|
.alert-action |
Inline action link within an alert, inheriting --color-alert. |
since 0.11.0
All classes
BUTTONS
| Class | Declares |
|---|---|
.loader |
width: var(--size-lg) |
.tag:hover |
color: var(--color-accent) |
.badge |
padding: 0 var(--space-d3) |
.badge.secondary, a.badge.secondary |
background-color: var(--color-surface) |
.badge.outline |
background-color: transparent |
.badge.ghost |
background-color: transparent |
.badge.destructive |
background-color: var(--color-surface) |
.alert |
font-family: var(--font-interface) |
.alert.error |
--color-alert: var(--color-error) |
.alert.success |
--color-alert: var(--color-success) |
.alert.info |
--color-alert: var(--color-info) |
.grid - Often used to layout multiple cards in columns * @see |
— |
.prose - Can be used inside card-body for rich content * * @link https://en.wikipedia.org/wiki/Edward_Tufte Information Design Pioneer * @link https://www.nngroup.com/articles/cards-component/ NN/g Cards Research * * @example html - Basic card structure * <article class="card"> * <header class="card-header"> * <h3>Card Title</h3> * </header> * <div class="card-body"> * <p>Card content with automatic spacing and rhythm.</p> * </div> * <footer class="card-footer"> * <a href="#">Read more →</a> * </footer> * </article> * * @example html - Cards in grid layout (3-column responsive) * <div class="grid"> * <article class="card col-4 col-sm-12"> * <div class="card-body"> * <h3>Feature One</h3> * <p>Description...</p> * </div> * </article> * <article class="card col-4 col-sm-12">...</article> * <article class="card col-4 col-sm-12">...</article> * </div> * * @example html - Clickable card (entire card is a link) * <a href="/article" class="card card-clickable"> * <div class="card-body"> * <h3>Article Title</h3> * <p>Preview text that entices you to click...</p> * </div> * </a> * * @example scss - Customizing card via CSS variables * .card.custom |
— |
.card - Base component * @see |
— |
.card > header:first-child |
background: var(--color-surface) |
.card > header:has(svg):first-child |
display: flex |
.card > footer:last-child |
background: var(--color-surface-low) |
.card.clickable |
text-decoration: none |
.inset, card.inset |
box-shadow: inset var(--shadow) !important |
.callout |
box-shadow: var(--shadow-raised), var(--shadow-ring) |
.callout[data-callout="important" i] |
--color-callout: var(--color-orange) |
.callout[data-callout*="red" i] |
--color-callout: var(--color-red) |
.callout[data-callout*="brown" i] |
--color-callout: var(--color-brown) |
.callout[data-callout*="orange" i] |
--color-callout: var(--color-orange) |
.callout[data-callout*="yellow" i] |
--color-callout: var(--color-yellow) |
.callout[data-callout*="green" i] |
--color-callout: var(--color-green) |
.callout[data-callout*="cyan" i] |
--color-callout: var(--color-cyan) |
.callout[data-callout*="blue" i] |
--color-callout: var(--color-blue) |
.callout[data-callout*="magenta" i] |
--color-callout: var(--color-magenta) |
.callout[data-callout*="purple" i] |
--color-callout: var(--color-purple) |
.callout[data-callout*="pink" i] |
--color-callout: var(--color-pink) |
.alert-action |
display: inline-block |
.skip-links |
position: absolute |
MENUS / POPOVERS
| Class | Declares |
|---|---|
.std-menu-content |
padding: var(--space-d4) |
.std-menu-label |
padding: var(--space-d4) |
.std-menu-separator |
all: unset |
.std-menu-item |
all: unset |
.scroll |
position: relative |
.field |
display: flex |