SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/avatars

8 CSS Avatars

7 Pure CSS1 with JSPublished 2026-10-04Free · no sign-up

Eight avatar patterns: initial avatars in four sizes, an overlapping group with a counter, story and presence rings, a name and role block, an editable profile photo, different shapes, a photo with an initials fallback and a team list with role selectors.

01. Avatar Sizes with Initials

AvatarSizes

Initial avatars in four sizes from one class and a size custom property, with colour picked per person. Initials are used when there is no photo; the element has role="img" and the person's full name as its accessible name.

View code
<div class="avs">
  <span class="av" style="--s:28px;--c:#7c3aed" role="img" aria-label="Ana Ruiz">AR</span>
  <span class="av" style="--s:40px;--c:#0ea5e9" role="img" aria-label="Ben Cole">BC</span>
  <span class="av" style="--s:56px;--c:#f97316" role="img" aria-label="Chi Okafor">CO</span>
  <span class="av" style="--s:72px;--c:#16a34a" role="img" aria-label="Dina Haddad">DH</span>
</div>
.avs { box-sizing: border-box; max-width: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }
.av { display: grid; place-items: center; width: var(--s); height: var(--s); border-radius: 50%; background: var(--c); color: #fff; font: 700 calc(var(--s) * .38) Inter, system-ui, sans-serif; }

02. Overlapping Avatar Group

AvatarStack

A stack of overlapping avatars with a +5 counter, used to show who is in a project. Negative margins create the overlap, a ring in the background colour separates each face, and the list has a label that says how many people there are.

View code
<ul class="avg" aria-label="9 team members">
  <li style="--c:#f472b6">MK</li><li style="--c:#60a5fa">JS</li><li style="--c:#34d399">AL</li><li style="--c:#fbbf24">RP</li><li class="more">+5</li>
</ul>
.avg { box-sizing: border-box; max-width: 100%; display: flex; margin: 0; padding: 0; list-style: none; font: 700 13px Inter, system-ui, sans-serif; }
.avg li { display: grid; place-items: center; width: 42px; height: 42px; margin-left: -10px; border: 3px solid #0e1118; border-radius: 50%; background: var(--c); color: #0e1118; }
.avg li:first-child { margin-left: 0; }
.avg .more { background: #262d3e; color: #e7ebf5; }

03. Avatar with Status Ring

AvatarPresence

Avatars with a coloured ring for stories or live status and a dot for online presence. The ring is a conic gradient behind the avatar, so it can show partial progress, and the status is included in each avatar's accessible name.

View code
<div class="avr">
  <span class="ring live" role="img" aria-label="Sam, live now"><span class="pic">S</span></span>
  <span class="ring story" role="img" aria-label="Lea, new story"><span class="pic">L</span></span>
  <span class="ring" role="img" aria-label="Tom, online"><span class="pic">T</span><i></i></span>
</div>
.avr { box-sizing: border-box; max-width: 100%; display: flex; gap: 22px; font: 800 20px Inter, system-ui, sans-serif; }
.ring { position: relative; display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; }
.live { background: conic-gradient(#ef4444, #f97316, #ef4444); }
.story { background: conic-gradient(#8b5cf6, #ec4899, #f59e0b, #8b5cf6); }
.pic { display: grid; place-items: center; width: 56px; height: 56px; border: 3px solid #fff; border-radius: 50%; background: #e0e7ff; color: #3730a3; box-sizing: border-box; }
.ring i { position: absolute; right: 2px; bottom: 2px; width: 14px; height: 14px; border: 3px solid #fff; border-radius: 50%; background: #16a34a; }

04. Avatar with Name and Role

ProfileInline

The avatar, name and role block used in comments, author bylines and team lists. A compact grid aligns the avatar with two lines of text, the avatar is decorative because the name is right next to it, and long names truncate cleanly.

View code
<ul class="avn">
  <li><span aria-hidden="true" style="--c:#38bdf8">PN</span><div><b>Priya Natarajan</b><small>Product designer</small></div></li>
  <li><span aria-hidden="true" style="--c:#fbbf24">OA</span><div><b>Olumide Adeyemi-Thompson</b><small>Engineering lead</small></div></li>
</ul>
.avn { box-sizing: border-box; max-width: 100%; width: 300px; display: grid; gap: 14px; margin: 0; padding: 0; list-style: none; font-family: Inter, system-ui, sans-serif; }
.avn li { display: grid; grid-template-columns: 44px minmax(0, 1fr); align-items: center; gap: 12px; }
.avn span { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; background: var(--c); color: #0e1118; font-weight: 800; font-size: 14px; }
.avn b { display: block; overflow: hidden; color: #fff; font-size: 15px; text-overflow: ellipsis; white-space: nowrap; }
.avn small { color: #9aa4b8; font-size: 13px; }

05. Editable Profile Photo

UploadForm

A profile picture with an edit button overlay for changing the photo. The button wraps a hidden file input so it opens the picker with keyboard and mouse, accepts images only, and previews the chosen picture immediately with an object URL.

View code
<div class="ape">
  <img id="ape-i" alt="Your profile photo" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'%3E%3Crect width='96' height='96' fill='%23dbeafe'/%3E%3Ccircle cx='48' cy='38' r='16' fill='%2393c5fd'/%3E%3Cpath d='M18 86c4-18 18-26 30-26s26 8 30 26' fill='%2393c5fd'/%3E%3C/svg%3E">
  <label class="edit"><input type="file" accept="image/*" id="ape-f"><span>Change photo</span></label>
</div>
.ape { box-sizing: border-box; max-width: 100%; position: relative; width: 112px; font-family: Inter, system-ui, sans-serif; }
.ape img { display: block; width: 112px; height: 112px; border-radius: 50%; object-fit: cover; box-shadow: 0 6px 18px -8px rgba(16,24,40,.4); }
.edit { position: absolute; right: -6px; bottom: 2px; }
.edit input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.edit span { display: inline-block; padding: 6px 10px; border: 2px solid #fff; border-radius: 999px; background: #101828; color: #fff; font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.edit input:focus-visible + span { outline: 2px solid #2563eb; outline-offset: 2px; }
document.getElementById('ape-f').addEventListener('change', e => {
  const f = e.target.files[0];
  if (f) document.getElementById('ape-i').src = URL.createObjectURL(f);
});

06. Avatar Shapes

AvatarShape

The same avatar in four shapes: circle, rounded square, squircle and hexagon. Shapes come from border-radius values and a clip-path polygon, so you can pick one per entity type, such as circles for people and squares for teams.

View code
<div class="avsh">
  <span class="c" role="img" aria-label="Circle avatar">AB</span>
  <span class="r" role="img" aria-label="Rounded square avatar">AB</span>
  <span class="q" role="img" aria-label="Squircle avatar">AB</span>
  <span class="h" role="img" aria-label="Hexagon avatar">AB</span>
</div>
.avsh { box-sizing: border-box; max-width: 100%; display: flex; flex-wrap: wrap; gap: 16px; }
.avsh span { display: grid; place-items: center; width: 56px; height: 56px; background: linear-gradient(135deg, #7c9cff, #a855f7); color: #fff; font: 800 17px Inter, system-ui, sans-serif; }
.avsh .c { border-radius: 50%; }
.avsh .r { border-radius: 10px; }
.avsh .q { border-radius: 38% 62% 45% 55% / 50% 40% 60% 50%; }
.avsh .h { clip-path: polygon(25% 4%, 75% 4%, 100% 50%, 75% 96%, 25% 96%, 0 50%); }

07. Photo Avatar with Fallback

ImageResilient

An avatar that shows a photo when it loads and falls back to initials when the image is missing or broken. The initials sit behind the image, and a one-line onerror handler hides a failed image so the fallback shows through.

View code
<div class="avf">
  <span class="wrap"><span class="ini" aria-hidden="true">JD</span><img alt="Jamie Dawson" src="https://example.invalid/missing.jpg" onerror="this.remove()"></span>
  <span class="label">Image failed, initials shown</span>
</div>
.avf { box-sizing: border-box; max-width: 100%; display: flex; align-items: center; gap: 14px; font: 500 14px Inter, system-ui, sans-serif; color: #475467; }
.wrap { position: relative; display: block; width: 56px; height: 56px; overflow: hidden; border-radius: 50%; }
.ini, .wrap img { position: absolute; inset: 0; width: 100%; height: 100%; }
.ini { display: grid; place-items: center; background: #fde68a; color: #78350f; font-weight: 800; }
.wrap img { object-fit: cover; }

08. Avatar List with Actions

ListTeam

A team member list with avatars, names, roles and a role selector for each person. Every select is labelled with the person's name, such as Role for Kim Lee, so a screen reader user knows whose role they are changing.

View code
<ul class="avl">
  <li><span style="--c:#f472b6" aria-hidden="true">KL</span><div><b>Kim Lee</b><small>kim@shop.co</small></div><select aria-label="Role for Kim Lee"><option>Owner</option><option>Editor</option></select></li>
  <li><span style="--c:#60a5fa" aria-hidden="true">RS</span><div><b>Raj Singh</b><small>raj@shop.co</small></div><select aria-label="Role for Raj Singh"><option>Editor</option><option>Owner</option></select></li>
  <li><span style="--c:#34d399" aria-hidden="true">EM</span><div><b>Eva Morel</b><small>eva@shop.co</small></div><select aria-label="Role for Eva Morel"><option>Viewer</option><option>Editor</option></select></li>
</ul>
.avl { box-sizing: border-box; max-width: 100%; width: 400px; margin: 0; padding: 4px 14px; list-style: none; border-radius: 14px; background: #12161f; font-family: Inter, system-ui, sans-serif; color-scheme: dark; }
.avl li { display: grid; grid-template-columns: 38px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid #222838; }
.avl li:last-child { border-bottom: 0; }
.avl span { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%; background: var(--c); color: #0e1118; font-weight: 800; font-size: 13px; }
.avl b { display: block; color: #fff; font-size: 14px; }
.avl small { color: #9aa4b8; font-size: 12.5px; }
.avl select { padding: 6px 8px; border: 1px solid #343c51; border-radius: 8px; background: #1a1f2c; color: #e7ebf5; font: 13px Inter, sans-serif; }

About these CSS Avatars

Name the person once

If the name is printed next to the avatar, hide the avatar from screen readers so the name is not read twice. When the avatar stands alone, give it role="img" and the person's name as its label.

Initials as a fallback

Layer initials behind the photo and remove the image if it fails to load. People without a photo still get a recognisable, coloured avatar instead of a broken image icon.

Status needs words

Online, away and busy dots should be described in text or in the avatar's accessible name. A green dot on its own means nothing to a screen reader or to someone who cannot see the colour.

Groups

Overlapping groups use negative margins and a ring in the background colour to separate faces. Label the list with the total, such as 9 team members, and show a +5 counter for the rest.

Frequently asked questions

Which demos need JavaScript?

The photo picker and the fallback handler. The others are CSS only.

What size should avatars be?

Around 32 to 40 pixels in lists and 64 to 96 on profile pages.

Can I use real photos?

Yes. Use img with object-fit: cover and alt text with the person's name.