Component Library

← Back to gallery

Profile header

Category: Layout · Tags: profile, avatar, user, header, stats

Priya Raman

Senior product designer

Lisbon, Portugal · Joined March 2024

Projects
24
Followers
1,280
Following
96

How to use it

Use at the top of a person's profile or team-member page. For a compact name and picture inside a list or comment, use a smaller user chip instead. Replace the name, role, stats and avatar (or swap the SVG for an <img> with empty alt), send the follow change to your server, and wire Message to your own conversation view.

Accessibility

The header is a <section> labelled by the person's name in an <h2>; the inline SVG avatar is decorative (aria-hidden, focusable="false") because the name sits right beside it. Stats are a <dl> so each number is read with its label, and Follow is a native toggle <button> with aria-pressed whose label stays "Follow" while its pressed state is announced and shown with a tick and a filled style. Text is #0f172a, #334155 and #475569 on white (17.85:1, 10.35:1, 7.58:1); Follow is #1d4ed8 on white (6.70:1, 8.01:1 hovered) and white on #1d4ed8 when pressed (6.70:1), with a 2px #1d4ed8 focus outline. It stacks into one column on narrow screens.

Source (copy-ready)

<section class="dcl-profile" aria-labelledby="dcl-profile-name">
  <svg class="dcl-profile__avatar" viewBox="0 0 96 96" width="96" height="96" aria-hidden="true" focusable="false"><circle cx="48" cy="48" r="48" fill="#dbeafe"/><circle cx="48" cy="38" r="17" fill="#1d4ed8"/><path d="M17 84c4-17 16-26 31-26s27 9 31 26z" fill="#1d4ed8"/></svg>
  <div class="dcl-profile__body">
    <h2 class="dcl-profile__name" id="dcl-profile-name">Priya Raman</h2>
    <p class="dcl-profile__role">Senior product designer</p>
    <p class="dcl-profile__meta">Lisbon, Portugal · Joined March 2024</p>
    <dl class="dcl-profile__stats">
      <div class="dcl-profile__stat"><dt class="dcl-profile__stat-label">Projects</dt><dd class="dcl-profile__stat-value">24</dd></div>
      <div class="dcl-profile__stat"><dt class="dcl-profile__stat-label">Followers</dt><dd class="dcl-profile__stat-value dcl-profile__followers" data-count="1280">1,280</dd></div>
      <div class="dcl-profile__stat"><dt class="dcl-profile__stat-label">Following</dt><dd class="dcl-profile__stat-value">96</dd></div>
    </dl>
  </div>
  <div class="dcl-profile__actions">
    <button type="button" class="dcl-profile__follow" aria-pressed="false"><span class="dcl-profile__tick" aria-hidden="true">+</span> Follow</button>
    <button type="button" class="dcl-profile__message">Message</button>
  </div>
</section>
<style>
.dcl-profile { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.25rem; max-width: 44rem; padding: 1.25rem; border: 1px solid #cbd5e1; border-radius: 0.75rem; font: inherit; color: #0f172a; background-color: #ffffff; }
.dcl-profile__avatar { flex: 0 0 auto; width: 6rem; height: 6rem; max-width: 100%; }
.dcl-profile__body { flex: 1 1 14rem; min-width: 0; }
.dcl-profile__name { margin: 0; font-size: 1.35rem; overflow-wrap: anywhere; color: #0f172a; background-color: #ffffff; }
.dcl-profile__role { margin: 0.15rem 0 0; font-weight: 600; color: #334155; background-color: #ffffff; }
.dcl-profile__meta { margin: 0.15rem 0 0; font-size: 0.9rem; color: #475569; background-color: #ffffff; }
.dcl-profile__stats { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin: 0.75rem 0 0; }
.dcl-profile__stat { display: flex; flex-direction: column-reverse; }
.dcl-profile__stat-label { font-size: 0.8rem; color: #475569; background-color: #ffffff; }
.dcl-profile__stat-value { margin: 0; font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; color: #0f172a; background-color: #ffffff; }
.dcl-profile__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.dcl-profile__follow, .dcl-profile__message { padding: 0.45rem 1rem; border: 1px solid #1d4ed8; border-radius: 6px; font: inherit; font-weight: 600; cursor: pointer; color: #1d4ed8; background-color: #ffffff; }
.dcl-profile__follow:hover, .dcl-profile__message:hover { color: #1e40af; background-color: #eff6ff; }
.dcl-profile__follow[aria-pressed="true"] { color: #ffffff; background-color: #1d4ed8; }
.dcl-profile__follow:focus-visible, .dcl-profile__message:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 2px; }
@media (max-width: 30rem) {
  .dcl-profile { flex-direction: column; align-items: flex-start; }
  .dcl-profile__body { flex-basis: auto; }
}
</style>
<script>
(function () {
  document.querySelectorAll(".dcl-profile").forEach(function (root) {
    if (root.dataset.dclBound) { return; }
    root.dataset.dclBound = "true";
    var follow = root.querySelector(".dcl-profile__follow");
    var tick = root.querySelector(".dcl-profile__tick");
    var count = root.querySelector(".dcl-profile__followers");
    if (!follow) { return; }
    follow.addEventListener("click", function () {
      var on = follow.getAttribute("aria-pressed") !== "true";
      follow.setAttribute("aria-pressed", on ? "true" : "false");
      if (tick) { tick.textContent = on ? "\u2713" : "+"; }
      if (count) {
        var base = Number(count.dataset.count) || 0;
        count.textContent = (base + (on ? 1 : 0)).toLocaleString("en-US");
      }
    });
  });
})();
</script>

Was this useful? Send feedback.