Home / Snippets / UI Components /

Image overlay card

Gradient overlay anchors text to the bottom of an image card using absolute positioning — no JavaScript.

Mountain trail at dusk

A peaceful evening hike through the alpine meadows.

Widely Supported
uino-jslayout

Quick implementation

.overlay-card {
  position: relative;
  border-radius: 0.75rem;
  overflow: hidden;
}

.overlay-card__image {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.overlay-card__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    oklch(0 0 0 / 0.75) 0%,
    oklch(0 0 0 / 0.2) 50%,
    transparent 100%
  );
}

.overlay-card__content {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 1.25rem;
}

.overlay-card__title {
  font-size: 1.1rem;
  font-weight: 700;
  color: oklch(1 0 0);
  margin: 0 0 0.25rem;
  line-height: 1.3;
}

.overlay-card__text {
  font-size: 0.8rem;
  color: oklch(0.85 0 0);
  margin: 0;
  line-height: 1.5;
}

Prompt this to your LLM

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

You are a senior frontend engineer building a media card component library.

Goal: An image card with a gradient overlay and text anchored to the bottom — no JavaScript.

Technical constraints:
- Use position: relative on the card wrapper and overflow: hidden to clip the image to border-radius.
- The overlay must use position: absolute with inset: 0 and a linear-gradient(to top, ...) from dark to transparent.
- Use oklch() for all gradient stops — e.g., oklch(0 0 0 / 0.75) for the dark bottom, transparent at the top.
- Use aspect-ratio: 4 / 3 with object-fit: cover on the image so it fills the card regardless of image dimensions.
- The text content must use position: absolute; bottom: 0; left: 0; right: 0 to anchor to the card bottom.
- Text must always be oklch(1 0 0) (white) to ensure legibility over the dark gradient.

Framework variant (pick one):
A) Vanilla CSS BEM classes: .overlay-card, .overlay-card__image, .overlay-card__overlay, .overlay-card__content.
B) React component — accept src, title, and description as props; render the overlay and content internally.

Edge cases to handle:
- Portrait images should not distort — rely on object-fit: cover, not fixed height.
- Card must not overflow its grid cell when placed in a CSS grid layout.
- Overlay div must have aria-hidden="true" so screen readers skip the decorative gradient.

Return CSS.

Why this matters in 2026

Image overlay cards are a staple of editorial, e-commerce, and portfolio layouts — blog grids, product tiles, and photo galleries all use this pattern. Getting the gradient right ensures text is legible over any image, regardless of photo brightness. A CSS-only implementation using position: absolute and linear-gradient is lighter and more composable than JavaScript-based text-shadow hacks or filter overlays.

The logic

position: relative on the card wrapper creates a stacking context so the position: absolute overlay and content children are anchored to the card rather than the viewport. overflow: hidden clips the image to the card's border-radius, ensuring no corners bleed out. The linear-gradient(to top, oklch(0 0 0 / 0.75) 0%, transparent 100%) fades from an opaque dark layer at the bottom — where the text sits — to fully transparent at the top, preserving the image detail while guaranteeing readable contrast. inset: 0 is shorthand for top: 0; right: 0; bottom: 0; left: 0, stretching the overlay to cover the entire card.

Accessibility & performance

Add aria-hidden="true" to the overlay element so assistive technologies skip the decorative gradient layer. Ensure the <img> has a meaningful alt attribute — the overlay is not a substitute for image description. White text on a 75% opaque black gradient typically achieves well above the 4.5:1 WCAG contrast ratio, but validate with real images where the gradient might be thinner. Use object-fit: cover with aspect-ratio to prevent layout shift as images load.