Home / Snippets / UI Components /

Feature card

A three-column feature card grid with icon, heading, and description — pure CSS, no JavaScript.

Fast performance

Optimised for speed with zero runtime overhead and compositor-friendly properties.

🎨

Themeable

Built on CSS custom properties so every token can be overridden per component.

Accessible

Semantic HTML and prefers-reduced-motion support baked in from the start.

Widely Supported
uino-jslayout

Quick implementation

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}

.feature-card {
  background: var(--card);
  border: 1px solid oklch(0.3 0.02 260);
  border-radius: 0.75rem;
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.feature-card__icon {
  font-size: 2rem;
  line-height: 1;
}

.feature-card__title {
  font-size: 1rem;
  font-weight: 700;
  margin: 0;
}

.feature-card__desc {
  font-size: 0.875rem;
  color: var(--muted);
  margin: 0;
}

@media (max-width: 48rem) {
  .feature-grid {
    grid-template-columns: 1fr;
  }
}

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are a senior frontend engineer building a CSS component library.

Goal: A reusable feature card grid — icon, heading, description — no JavaScript.

Technical constraints:
- Use CSS Grid with repeat(3, 1fr) for the three-column layout.
- Cards use var(--card) background, a subtle oklch() border, border-radius, and padding.
- Use flexbox inside each card (flex-direction: column, gap) for vertical rhythm.
- Use oklch() for all color values, not hex or rgba().
- Include a responsive breakpoint that stacks to a single column below 48rem.

Framework variant (pick one):
A) Vanilla CSS with BEM class names (.feature-card, .feature-card__icon, etc.).
B) React component — accept an array of { icon, title, description } objects as a prop.

Edge cases to handle:
- Cards with long descriptions should not break the grid (use align-items: start on the grid).
- Icon area should not shrink if the heading is long (flex-shrink: 0 on icon).
- Grid gap must use a relative unit, not px, for scalable spacing.

Return HTML and CSS.

Why this matters in 2026

Feature card grids are the workhorse of marketing pages, dashboards, and documentation sites. A well-structured card with a clear icon, heading, and description communicates value instantly. CSS Grid makes three-column layouts trivial without a framework, and using CSS custom properties for colours and spacing keeps the whole thing theme-ready.

The logic

grid-template-columns: repeat(3, 1fr) distributes all three cards equally across the available width. Each card is a flex column — flex-direction: column with gap replaces all the margin stacking that used to plague card layouts. The border uses an oklch() value slightly lighter than the card background, creating a visible edge without harsh contrast. The responsive override at 48rem collapses the grid to a single column for mobile without any JavaScript or layout recalculation.

Accessibility & performance

Use semantic heading levels inside cards — if cards live inside a section with an <h2>, the card title should be an <h3>. Avoid using div click handlers on the whole card; instead keep the "learn more" action as an <a> element so keyboard users can navigate to it. CSS Grid layout does not trigger layout recalculations on scroll, making this pattern compositor-friendly even with many cards on screen.