Advertisement

Interactive Radial Image Carousel

| by Vladimir | 3 min read | code by Chris Bolson
Advanced

Tech & Dependencies

HTML CSS

Features

  • CSS Motion Path
  • Sibling Targeting
  • Spring Physics
  • Pure CSS

Browser Support

Chrome 119+ Edge 119+ Firefox (partial) Safari 26.2+

Core

This is an Interactive Radial CSS Image Carousel. It arranges a deck of image cards into a curved, fan-like layout. Its function is to provide an engaging, space-saving gallery interface where hovering over a card gracefully shifts its neighbors away along a circular path, bringing the focused item into clear view without relying on JavaScript math.

Specs

  • Weight: ~2 KB. Zero dependencies. No JavaScript.
  • Performance: High. The browser’s native CSS engine handles the complex mathematical positioning via the Motion Path API, allowing smooth GPU-accelerated interpolation during hover states.
  • Theming / Customization: Fully parameterized via CSS variables. You can easily adjust the curve radius (--radius), the spread of the cards (--arc-size), and the physical bounce of the animation (--card-trans-easing).
  • Responsiveness: Fluid. Elements use viewport relative units (vmin), ensuring the entire fan structure scales perfectly across desktop and mobile screens.
  • Graceful Degradation: [!] Highly experimental. Relies heavily on sibling-count(), sibling-index(), and the :has() pseudo-class. In unsupported browsers, the component includes @supports not blocks as a rudimentary fallback to hardcode indices, but without offset-path support, the cards will simply stack flat on top of each other.

Anatomy

The component relies on absolute positioning tethered to a mathematically defined invisible path.

  • HTML (The Skeleton): A single .wrapper container holding a flat list of <div> elements, each wrapping an <img>.
  • CSS (The Skin): Utilizes offset-path: circle() to define the invisible track. It uses complex calc() functions to determine the exact percentage distance (offset-distance) each card should travel along that circle.
  • JS (The Nervous System): Absent. The logic is strictly state-driven.

Logic

The standout technical achievement is “Radial Sibling Displacement” using the :has() combinator:

/* Card pushes right-side neighbors forward */
&:hover {
  & + div { --arc-shift: calc(var(--arc-shift-delta) * 3); }
  & + div + div { --arc-shift: calc(var(--arc-shift-delta) * 2); }
}
/* Card pushes left-side neighbors backward */
&:has(+*:hover) {
  --arc-shift: calc(var(--arc-shift-delta) * -3);    
}

Instead of using JS to recalculate the positions of every card in an array, the CSS engine dynamically updates the --arc-shift variable based on structural relationships. When a card is hovered, the adjacent sibling combinator (+) shifts the next few cards positively along the arc. Simultaneously, the :has() pseudo-class looks backwards up the DOM tree, shifting the preceding cards negatively. The transition property then smoothly animates the resulting change in offset-distance.

Feel

Elastic and deeply organic. The complex linear() easing function mimics physical spring tension. When you hover over a card, it feels like parting physical objects on a curved string; the targeted card pops up slightly (offset-anchor), while its neighbors reluctantly yield space, rippling outward before springing back into place when the cursor leaves.

Advertisement