Home / Snippets / Animation /

Image zoom transition

Hover an image to zoom in smoothly — overflow: hidden keeps the frame clean.

Landscape
Mountain view
Portrait
Studio shot
Abstract
Color study
Widely Supported
animationno-js

Quick implementation

/* Image zoom on hover */
.img-frame {
  overflow: hidden;
  border-radius: 0.5rem;
}

.img-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

.img-frame:hover img,
.img-frame:focus-within img {
  transform: scale(1.15);
}

/* Optional: gradient overlay on hover */
.img-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    oklch(0 0 0 / 0.6), transparent);
  opacity: 0;
  transition: opacity 0.4s ease;
}

.img-frame:hover::after {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .img-frame img,
  .img-frame::after {
    transition-duration: 0.01s;
  }
}

Prompt this to your LLM

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

You are a senior frontend engineer building image gallery components.

Goal: Smooth image zoom on hover using transform: scale() inside an overflow: hidden container.

Technical constraints:
- Use transform: scale(1.1–1.2) on the image — it's GPU-composited and doesn't trigger layout.
- Parent container must have overflow: hidden and position: relative.
- Use cubic-bezier(0.4, 0, 0.2, 1) for natural deceleration.
- Use oklch() for all color values — no hex or rgba().
- Optional: add a gradient overlay that fades in on hover using a ::after pseudo-element.

Framework variant (pick one):
A) Vanilla HTML + CSS only.
B) React component — accept src, alt, and caption props, show caption overlay on hover.

Edge cases to handle:
- Respect prefers-reduced-motion: reduce duration to near-instant.
- Ensure object-fit: cover is set so the image fills the frame correctly during zoom.
- Include :focus-within for keyboard accessibility.

Return HTML + CSS.

Why this matters in 2026

Image zoom on hover is one of the most common micro-interactions in galleries, product pages, and portfolios. Using transform: scale() instead of changing width/height keeps the animation on the compositor thread — no layout thrashing, no jank, even on image grids with dozens of items. The overflow: hidden on the parent cleanly clips the zoomed image to the card boundary.

The logic

The parent container has overflow: hidden and a fixed size. The image inside uses object-fit: cover to fill the frame and transition: transform 0.5s. On :hover, transform: scale(1.15) enlarges the image — the overflow clips it, creating a "zoom into" effect. An optional ::after pseudo-element with a gradient background fades in on hover to add a dark overlay for caption text.

Accessibility & performance

transform transitions are the gold standard for performance — they run on the GPU without triggering layout or paint. Include :focus-within on the container so keyboard users can trigger the zoom by tabbing to a link or button inside the card. Gate animations behind prefers-reduced-motion. Ensure images have proper alt text for screen readers.