Avatar Group — Free HTML CSS JS Snippet

Avatar Group · Cards · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Negative margin-left: -8px creates the overlap stack effect
border: 2.5px solid #fff on each av — white ring separates overlapping avatars
Hover lift: translateY(-3px) + z-index:10 brings hovered av to front
Pure CSS tooltip: .av-tip opacity 0→1 on .av-wrap:hover, no JavaScript
av-more pill: same height/border as avatars, blends into the stack
Spring add animation: scale(0)→scale(1) cubic-bezier(0.34,1.56,0.64,1) overshoot
requestAnimationFrame ensures scale(0) paints before transition triggers
Four variants: basic / tooltipped / small reaction / interactive add

About this UI Snippet

Avatar Group — Overlapping Stack, Tooltip Names, +N Overflow, Hover Lift & Add Member

Screenshot of the Avatar Group snippet rendered live

An avatar group (also called an avatar stack) shows multiple user avatars overlapping horizontally — a compact way to communicate who is involved in a project, who liked a post, who is viewing a document, or who is on a team (the team presence list shows the same data expanded). This snippet provides four avatar group variants: a basic overlap stack with +N overflow count, a tooltipped version showing names on hover, a small reaction row for post likes, and an interactive add-member button with a spring-entrance animation for newly added avatars.

The negative margin-left overlap

The overlap effect uses margin-left: -8px on all avatars except the first. This pulls each avatar 8px under the previous one. The border: 2.5px solid #fff creates a white ring that separates each avatar from the one behind it. Together these create the classic stacked avatar appearance. The negative margin value controls the overlap amount — -8px gives moderate overlap; -12px creates tighter stacking.

The hover lift effect

Each .av has transition: transform 0.15s, z-index 0.15s. On :hover, transform: translateY(-3px) lifts the hovered avatar up slightly, and z-index: 10 brings it to the front. This interactivity communicates that each avatar is distinct and hoverable — useful when tooltips or click handlers are attached.

The tooltip name on hover

The .tooltipped variant wraps each avatar in .av-wrap. Inside, a .av-tip span sits above the avatar via position: absolute; bottom: calc(100% + 6px). It starts at opacity: 0 and transitions to opacity: 1 on .av-wrap:hover. No JavaScript needed — the same pure CSS tooltip pattern triggered by the parent hover. For per-user presence dots, see the status avatar.

The +N overflow count

The .av-more element shows how many additional members are not displayed. It uses a pill shape (border-radius: 999px) with the same border and dimensions as the avatars, so it blends seamlessly into the stack. Update the text to reflect the actual count: '+' + (totalMembers - shownAvatars).

The spring add-member animation

When a new avatar is added, it starts at scale(0) and transitions to scale(1) using cubic-bezier(0.34,1.56,0.64,1) — a spring curve with overshoot. requestAnimationFrame ensures the scale(0) state is painted before the transition starts, triggering the spring entrance.

Using real images with initials fallback

Replace the .av div with an img element: <img class="av" src="user.jpg" alt="Alex Johnson">. The border, border-radius, hover, and negative margin styles apply automatically. For error handling when the image fails to load, use the onerror attribute: onerror="this.outerHTML='<div class='av' style='--bg:linear-gradient(135deg,#6366f1,#a78bfa)'>AJ</div>'". This replaces the broken image with the gradient initials fallback without JavaScript setup.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Rather than working out the overlap math by eye, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why the overlap uses negative margin-left instead of absolute positioning, and why that choice matters when an avatar is removed from the group. The same assistant is useful for optimizing it — ask whether the addMember() function's requestAnimationFrame-before-transition pattern is really necessary here, and what would happen visually if it were removed. It's also a good partner for extending the component: ask it to add a remove animation that mirrors the spring-in entrance, wire the +N overflow bubble to open a full member list on click, or swap the gradient initials for real photos with a graceful onerror fallback. 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 "overlapping avatar group" in plain HTML, CSS, and JavaScript — no libraries.

Requirements:
- A row of circular avatars where every avatar after the first uses a negative margin-left to overlap the previous one, with a solid white border ring on each avatar so overlapping circles stay visually distinct against each other, and where removing an avatar from the DOM should shrink the group's total width automatically because the layout is based on normal document flow (not absolute positioning).
- Every avatar should lift up slightly and rise to the front (via a CSS transform and a higher z-index) on hover, without disturbing the layout of neighboring avatars.
- A final "+N" pill styled to match the avatar dimensions and border, showing the count of members not otherwise displayed.
- A separate tooltip variant where each avatar is wrapped in its own relatively-positioned container with an absolutely positioned name label above it that fades in and slides up on hover, driven entirely by CSS opacity and transform on a parent hover selector — no JavaScript mouseenter/mouseleave listeners for this part.
- An "add member" interactive button that, when clicked, creates and inserts a new avatar element starting at scale(0), forces a style flush with requestAnimationFrame before removing that inline transform so a CSS transition with a bounce/overshoot easing curve animates it in, and hides the add button once a fixed list of candidate members is exhausted.

Step by step

How to Use

  1. 1
    Hover over avatars to see the lift and tooltip effectsEach avatar in the tooltipped row shows a name tooltip above it on hover. All avatars lift slightly on hover with a translateY(-3px) transition, bringing them to the front via z-index.
  2. 2
    Click the + button to add members with a spring animationThe + dashed button adds avatars one by one with a spring bounce entrance (cubic-bezier overshoot). After 3 additions, the button hides — update NAMES array and the added limit for your use case.
  3. 3
    Change the overlap amountUpdate margin-left: -8px on .av-group .av to control overlap. Use -6px for less overlap (more breathing room), -12px for tighter stacking, -16px for heavy overlap like GitHub contributor groups.
  4. 4
    Update the +N overflow countEdit the .av-more text to reflect your actual count: totalMembers - shownAvatars. Show it only when there are hidden members. For 12 total with 4 shown: <div class="av-more">+8</div>.
  5. 5
    Use real images instead of initialsReplace the .av div with <img class="av" src="avatar.jpg" alt="Name" style="object-fit:cover">. The border, border-radius, and hover styles apply automatically. Add a fallback initials div for when images fail to load.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component mapping a users array to avatar elements, or "Tailwind" for a React + Tailwind CSS version.

Real-world uses

Common Use Cases

Team member display in project and board cards
Show who is working on a project in Kanban cards, task items, and project listings. The +N overflow communicates team size without listing every member. Clicking the group can open a full member list panel.
Document viewer and shared file presence indicators
Show who is currently viewing a document in real time. Update the avatar stack via WebSocket as users open and close the document. The animated add/remove gives instant visual feedback when someone joins or leaves.
Post reactions and social proof engagement
The small reaction row variant shows "Alex, Sara and 14 others liked this" — a compact social proof pattern used across LinkedIn, Facebook, and community platforms. Link the avatar group to a reaction detail panel on click.
Meeting and event attendee lists
Show event attendees or meeting participants in calendar items and event cards. The overlap stack communicates "multiple people" at a glance. The add-member button lets users invite more attendees inline.
Study the negative margin overlap and border separation technique
The avatar stack uses negative margin (not absolute positioning) so the group shrinks naturally when avatars are removed. The white border separation trick is applicable to any overlapping element — chips, cards, images — not just avatars.
Code repository and pull request contributor displays
GitHub, GitLab, and Bitbucket use avatar groups for PR reviewers, commit contributors, and repository collaborators. The group shows at most 4-5 avatars with a +N count for larger teams. Clicking the group shows all contributors.

Got questions?

Frequently Asked Questions

margin-left: -8px on each .av (except the first) pulls the avatar 8px to the left, overlapping the previous avatar. Unlike absolute positioning, this keeps the avatars in the normal document flow — the group's total width shrinks accordingly. The border: 2.5px solid #fff ring on each avatar creates a white separation band that makes each avatar visually distinct despite the overlap. The negative margin value controls overlap: -6px gives light overlap, -16px gives heavy overlap like GitHub contributor grids.

Wrap each .av in a .av-wrap div and add a .av-tip span: <div class="av-wrap"><div class="av">AJ</div><span class="av-tip">Alex Johnson</span></div>. CSS: .av-tip { position:absolute; bottom:calc(100%+6px); left:50%; transform:translateX(-50%); opacity:0; transition:opacity 0.15s; } .av-wrap:hover .av-tip { opacity:1; }. This is a pure CSS tooltip — no JavaScript hover handlers needed.

Add a .removing class to the avatar: av.classList.add("removing"); with CSS .av.removing { transform: scale(0); opacity: 0; transition: transform 0.25s, opacity 0.25s, margin-left 0.25s; margin-left: 0; width: 0; border: none; padding: 0; }. After the transition, call av.remove(). The margin-left: 0 and width: 0 collapse the avatar's space in the flow after it shrinks, preventing a gap. Use transitionend to fire the removal.

Click "JSX" to download. Accept a users prop (array of { name, initials, gradient }) and maxVisible (default 4). Map the first maxVisible users to .av elements. Show the overflow count if users.length > maxVisible: {users.length > maxVisible && <div className="av-more">+{users.length - maxVisible}</div>}. For the add-member button, manage a showingMembers state array and add to it on click. Derive the gradient from the user object or compute from the user id for consistent colours.