webdevpuneet.com

Profile Completion Meter — HTML CSS JS Snippet

Profile Completion Meter · Dashboards · Plain HTML, CSS & JS · Live preview

CategoryDashboards

Copy & paste

Source Code

<div class="pc-card" id="pcCard">
  <div class="pc-top">
    <div class="pc-ring">
      <svg viewBox="0 0 100 100" width="96" height="96">
        <circle class="pc-track" cx="50" cy="50" r="42"/>
        <circle class="pc-prog" id="pcProg" cx="50" cy="50" r="42"/>
      </svg>
      <div class="pc-pct"><span id="pcPctNum">0</span><small>%</small></div>
    </div>
    <div class="pc-intro">
      <h2 class="pc-title">Complete your profile</h2>
      <p class="pc-msg" id="pcMsg">Finish setup to unlock everything.</p>
    </div>
  </div>

  <ul class="pc-list" id="pcList">
    <li class="pc-task done" data-w="20" onclick="toggleTask(this)"><span class="pc-check"></span><span class="pc-label">Add a profile photo</span><span class="pc-pts">+20%</span></li>
    <li class="pc-task done" data-w="20" onclick="toggleTask(this)"><span class="pc-check"></span><span class="pc-label">Verify your email</span><span class="pc-pts">+20%</span></li>
    <li class="pc-task" data-w="15" onclick="toggleTask(this)"><span class="pc-check"></span><span class="pc-label">Write a short bio</span><span class="pc-pts">+15%</span></li>
    <li class="pc-task" data-w="20" onclick="toggleTask(this)"><span class="pc-check"></span><span class="pc-label">Connect an integration</span><span class="pc-pts">+20%</span></li>
    <li class="pc-task" data-w="15" onclick="toggleTask(this)"><span class="pc-check"></span><span class="pc-label">Invite a teammate</span><span class="pc-pts">+15%</span></li>
    <li class="pc-task" data-w="10" onclick="toggleTask(this)"><span class="pc-check"></span><span class="pc-label">Set up billing</span><span class="pc-pts">+10%</span></li>
  </ul>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Weighted completion
Each task has a data-w weight; targetPct scores completed weight over total, so high-impact steps move the ring more.
SVG stroke-dash ring
Two circles with stroke-dasharray = circumference and a shrinking stroke-dashoffset draw the arc, rotated to start at the top.
JS-tweened ring
setRing animates the offset each requestAnimationFrame with an ease-out — smooth and export-safe, unlike a CSS stroke transition.
Eased percentage count
The centre number counts up from the same eased value as the ring, so they always agree.
Animated checklist
Tasks toggle a done state with a check-circle fill and strike-through label, with hover feedback per row.
Contextual messaging
message returns encouragement by threshold, turning a static label into a motivating nudge.
Complete state
At 100% the card recolours the ring green and emphasises the message, marking the goal as achieved.
Self-recomputing
All values derive from the checklist DOM, so adding or reweighting tasks needs no other code changes.

About this UI Snippet

Profile Completion Meter — Weighted Checklist, Animated Progress Ring & Complete State

Screenshot of the Profile Completion Meter snippet rendered live

The profile completion meter is one of the most effective onboarding nudges in SaaS: a progress ring paired with a checklist of setup tasks that visibly fills as users complete each step. It leverages the Zeigarnik effect — people are driven to finish what they have started — and measurably increases activation. This snippet implements it in plain HTML, CSS, and vanilla JavaScript: a weighted task checklist, an animated SVG progress ring, an eased percentage count-up, and a celebratory complete state.

Weighted tasks, not just a count

Each task carries a data-w weight (photo 20%, verify email 20%, bio 15%, integration 20%, invite 15%, billing 10%) summing to 100. targetPct recomputes completion as the sum of completed weights over the total — so higher-impact steps move the needle more, exactly as real onboarding scores work. Tasks start with some pre-completed (photo + email = 40%), and clicking any row toggles its done state, checks it off with a strike-through, and recalculates.

Animated SVG progress ring

The ring is two SVG circles (track + progress) using the stroke-dash technique: stroke-dasharray set to the circumference (2πr) and stroke-dashoffset reduced toward zero to draw the arc, rotated -90deg to start at the top. Rather than a CSS transition on stroke-dashoffset (which utility frameworks like Tailwind do not animate, so it would snap), setRing tweens the offset every frame with a requestAnimationFrame loop and a cubic ease-out, animating smoothly from the previously shown value to the new target. The centre percentage counts up in lockstep from the same eased value.

Contextual messaging and complete state

The supporting message changes with progress — "Nice start!", "Almost there", and on 100% "Profile complete 🎉 You are all set!" — turning a static label into encouragement. At 100% the card gains a complete class that recolours the ring green and emphasises the message, marking the goal as achieved. These small reinforcements are what make completion meters convert.

Self-recomputing

Everything derives from the checklist DOM: targetPct reads the tasks each time, so adding, removing, or reweighting tasks needs no other changes, and the ring/percentage/message all follow. On load it computes the initial percentage and message from the pre-completed tasks.

Wire each task's click to actually open that setup step (or mark it done from your backend) and you have a real onboarding widget. Pair this with a stats card for account metrics, an onboarding tour for guided setup, or a streak tracker for ongoing engagement.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA "Complete your profile" card appears with a progress ring at 40% and a six-item checklist (two pre-completed).
  2. 2
    Complete a taskClick "Write a short bio" — it checks off with a strike-through and the ring animates up, the percentage counting smoothly.
  3. 3
    Watch the message changeAs you pass thresholds the supporting text updates from "Nice start!" to "Almost there".
  4. 4
    Undo a taskClick a completed task again to uncheck it — the ring eases back down and the percentage recalculates.
  5. 5
    Reach 100%Finish every task — the ring turns green and the message becomes "Profile complete 🎉 You are all set!".
  6. 6
    Wire real stepsMake each task's click open that setup flow or sync its done state from your backend; the meter recomputes automatically.

Real-world uses

Common Use Cases

SaaS onboarding nudges
The core use — drive activation by showing setup progress. Pair with an onboarding tour for guided steps.
Account / profile settings
Show completion in a settings or profile page beside a stats card of account info.
Seller / creator setup
Marketplaces nudge sellers to complete a storefront (add photos, payout, policies) before going live.
Verification / KYC flows
Track multi-step identity or compliance steps with weights reflecting each step's importance.
Course / learning progress
Show progress through required modules; combine with a streak tracker for daily engagement.
Checklist dashboards
Any weighted task list with a visual progress goal in a dashboard layout.
Related: Video Call Hand-Raise Queue
See the Video Call Hand-Raise Queue for a related dashboards pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

On load, set each task's done class from your user record, then call setRing(targetPct()). In toggleTask, after toggling, PATCH the change to your API (optimistically); on failure, revert the class and recompute. Make each row's click open the actual setup step (navigate or open a modal) rather than just toggling, so the checklist drives real completion.

Edit each task's data-w. They do not need to sum to 100 — targetPct divides completed weight by the total of all weights, so any numbers work and the percentage stays correct. Weight steps by impact (e.g. connecting an integration is worth more than adding a bio) to reflect what actually matters for activation.

Utility frameworks like Tailwind do not include stroke-dashoffset in their transition utility, so a CSS-transition approach snaps in the React + Tailwind export. Updating the offset each requestAnimationFrame (with an ease-out) animates smoothly everywhere and lets the centre percentage count up in perfect sync from the same value.

Give the ring role="progressbar" with aria-valuenow/aria-valuemax updated in setRing, and make each task a real interactive element (button or checkbox) so it is keyboard-operable and announces its checked state. Announce the new percentage via an aria-live="polite" region so screen-reader users hear progress as they complete steps.

In React, hold the tasks (with done flags) in useState, derive the percentage with useMemo, and animate the ring with a small tween effect or by setting the offset from an animated value. In Vue, use a ref for tasks and a computed percentage. In Angular, track tasks on the component and bind [style.strokeDashoffset]. The stroke-dash math and checklist CSS port unchanged.