Source Code

<div class="fe-stage">
  <p class="fe-hint">Hover any avatar — the whole stack fans apart around it</p>
  <div class="fe-stack" id="feStack"></div>
</div>

Avatar Stack Fan Expand — Hover Group Animation Snippet

Avatar Stack Fan Expand · Animations · Plain HTML, CSS & JS · Live preview

What's included

Features

Hovering one avatar displaces every other avatar, not just the hovered one
Push distance grows proportionally with stack-order distance from the hovered avatar
Hovered avatar lifts and scales instead of sliding horizontally like its neighbors
z-index dynamically promoted on hover so the focused avatar always renders on top
Overshoot cubic-bezier transition gives the fan-out and collapse an elastic snap
Stack rendered entirely from a data array — add or remove members with no HTML edits
Direction-aware displacement — avatars to the left push left, avatars to the right push right
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons
Live split-pane editor — preview updates as you type

About this UI Snippet

Avatar Stack Fan Expand — Proportional Neighbor Displacement on Single-Avatar Hover

Screenshot of the Avatar Stack Fan Expand snippet rendered live

A standard overlapping avatar stack lifts only the single avatar under the cursor, leaving its overlapping neighbors untouched underneath it. This variant treats the whole stack as one connected group: hovering any single avatar pushes every other avatar apart, with avatars farther along the stack order moving proportionally further, so the entire row visibly fans open around whichever member is highlighted rather than just popping one circle forward.

Building the stack from data

An array of PEOPLE objects (initials and a color) is rendered into .fe-avatar elements appended to the stack container, each stamped with a data-index and a descending inline z-index so earlier avatars sit visually on top of later ones at rest — matching the usual overlapping-circle stack look.

The displacement formula

On mouseenter of avatar at index i, every other avatar at index j computes delta = j - i — how far away it sits in the stack order, and in which direction. The direction is just the sign of delta. The push distance is SPREAD * (1 + (Math.abs(delta) - 1) * 0.4) — so the immediate neighbor moves by roughly SPREAD pixels, and each avatar one step further out moves progressively more (a 40% increase per extra step), which is what makes the fan read as opening from a single point rather than every avatar sliding by the exact same fixed amount.

The hovered avatar's own treatment

The avatar actually under the cursor doesn't translate horizontally with the rest — it lifts vertically (translateY(-10px)) and scales up slightly, both to distinguish it as the interaction's focus and to avoid it fighting visually with neighbors sliding away from directly underneath it. Its z-index is also bumped above every other avatar so it renders on top regardless of its original stack position.

Resetting the fan

On mouseleave, every avatar's transform resets to translateX(0) translateY(0) scale(1) and the hovered avatar's z-index returns to its original stack-order value. The cubic-bezier(0.34, 1.56, 0.64, 1) transition applied to transform (and to margin-left, in case you also adjust overlap on hover) includes overshoot, giving both the fan-out and the collapse-back a small elastic snap.

Tuning the spread

Increase SPREAD for a wider fan; decrease the 0.4 multiplier in the offset formula to make the fan-out distance grow more evenly across the stack instead of accelerating toward the outer edges.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to design the displacement curve from scratch. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why the offset formula uses (Math.abs(delta) - 1) * 0.4 rather than a flat SPREAD * delta, and what visual difference that non-linear growth makes compared to a purely linear fan. The same assistant can help optimize it — for instance asking whether recalculating every avatar's transform on every mouseenter is cheap enough for a stack of 20+ members, or whether it should be throttled. It's also useful for extending the effect: ask it to make the fan also happen on keyboard focus for accessibility, add a subtle rotation to each fanned avatar based on its direction, or combine this with the jelly press button's spring physics for a bouncier fan-out. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build an "avatar stack fan expand" hover effect in plain HTML, CSS, and JavaScript with no libraries.

Requirements:
- An overlapping row of circular avatar elements (negative margin-left so each one overlaps the previous), rendered from a JavaScript array of person data (initials and a color) rather than hardcoded HTML for each avatar.
- On mouseenter of any one avatar, every OTHER avatar in the stack must translate horizontally away from it — avatars to its left move further left, avatars to its right move further right — with the displacement distance growing the farther an avatar sits (in stack order) from the hovered one, not a uniform fixed distance for every neighbor.
- The hovered avatar itself must not slide horizontally with the others; give it a distinct visual treatment instead, such as lifting vertically and scaling up slightly, and temporarily raise its z-index above all other avatars so it renders on top regardless of its position in the stack order.
- On mouseleave, all avatars must animate back to their neutral overlapping position and the hovered avatar's z-index must return to its original stack-order-based value.
- Use a CSS transition with an overshoot easing curve (a cubic-bezier with a control point above 1) on the transform property so both the fan-out and the collapse-back have a small elastic quality.
- Keep the avatar data and rendering data-driven: adding or removing a person from the source array should automatically update the rendered stack and the hover math with no other code changes.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Hover any avatarMove your cursor over any circle in the stack — every other avatar slides apart from it, with farther ones moving proportionally more.
  2. 2
    Move between avatarsHover a different avatar and the fan recalculates instantly around the new hovered member.
  3. 3
    Move the cursor awayLeave the stack and every avatar springs back to its overlapping resting position.
  4. 4
    Edit the people listUpdate the PEOPLE array in the JS panel — initials, colors, and count all drive the rendered avatars automatically.
  5. 5
    Adjust the fan widthChange the SPREAD constant and the 0.4 growth multiplier in the offset formula to control how wide the fan opens.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

Team and collaborator lists
Show who is working on a document or project. Fanning the stack open on hover makes it easy to individually inspect each collaborator, unlike a static avatar stack alone.
CARD
Reviewer and approver rows
On an approval workflow card, fan open the reviewer stack on hover so each reviewer's avatar is momentarily easier to click or inspect individually.
Learn proportional group displacement
A compact example of computing per-element offsets based on relative position to a single "source" element — a pattern reusable for menus, carousels, and dock-style navigation.
Testimonial / social proof avatar rows
A row of customer avatars on a landing page becomes more interactive and inviting to explore with the fan-expand hover treatment.
Live collaboration presence indicators
Pair with avatar stack tooltip to fan the stack open and reveal each member's tooltip individually as the cursor moves across the group.
Related: Icon Grid Neighbor Pull
See the Icon Grid Neighbor Pull snippet for the opposite interaction — hovering one element attracts its neighbors instead of pushing them apart.
Related: Elastic Spring Toggle Switch
See the Elastic Spring Toggle Switch for a related animations pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

On hover, every non-hovered avatar computes delta = its own index minus the hovered avatar's index. The push distance is SPREAD * (1 + (Math.abs(delta) - 1) * 0.4) — so the immediate neighbor moves roughly SPREAD pixels, and each avatar further along the stack order moves progressively more.

The hovered avatar lifts vertically and scales up rather than sliding horizontally, so it reads clearly as the focus of the interaction rather than competing visually with the neighbors sliding away underneath it.

At rest, earlier avatars in the PEOPLE array have a higher z-index so they overlap later ones, matching the standard stacked-avatar look. On hover, the hovered avatar's z-index is temporarily bumped above every other avatar so it always renders on top regardless of its position in the array.

Yes. Swap the translateX offset calculation for a translateY offset (and adjust the base stack layout from flex-row to flex-column) to fan the avatars open in a vertical list instead of a horizontal row.

Edit the PEOPLE array in the JS panel — each object needs initials and a color. The render loop and hover logic both read directly from this array, so no other code needs to change.

Yes. Click "JSX" for a React component. Store PEOPLE in state or props, render one element per person with a ref array, and compute the same delta-based offset inside onMouseEnter, applying the resulting transform to each ref rather than triggering a state update per frame.