More Dashboards Snippets
User Stats Card — Free HTML CSS JS Snippet
User Stats Card · Dashboards · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
User Stats Card — Activity Heatmap, Progress Arc & Follow Toggle

A user stats card displays a developer profile with activity metrics, a contribution heatmap, skill progress, and social stats. Used on portfolio sites, developer dashboards, and community platforms.
The activity heatmap
The heatmap is built from DOM elements, not canvas. A JS loop creates 12 columns × 7 rows of divs. Each div gets a random background colour from the levels array (from light grey to deep blue) simulating contribution frequency. The break-inside: avoid CSS on cells prevents grid rows from wrapping.
Circular progress bar
The skill progress uses the same SVG stroke-dashoffset technique as the SVG Progress Ring snippet: stroke-dasharray: CIRCUMFERENCE and stroke-dashoffset: CIRCUMFERENCE * (1 - pct/100). The ring animates from 0 to the target value on page load.
Follow button toggle
The follow button toggles between "Follow" and "Following" states via .following class — the same pattern as the Social Post Card snippet.
The activity heatmap
The contribution heatmap is a 52-week × 7-day grid of small squares. Each square corresponds to one day. The colour intensity (from light grey to deep indigo) represents activity count on that day — 0 activity is the lightest; maximum activity is the darkest. JavaScript generates the grid using nested loops: for each week (column), create 7 day squares and append to the grid container. Random or real activity data determines each square's colour class.
The circular progress rings
Multiple SVG progress rings use the stroke-dashoffset technique to show different skill or metric percentages. Each ring has a different radius, colour, and target value. The rings animate simultaneously when the component mounts or scrolls into view. See the SVG Progress Ring snippet in this library for the full mathematics explanation.
The follow button state
The follow button toggles between "Follow" and "Following" states using a CSS class and a click handler. The button border and text colour change on toggle. In a real app, the click triggers a POST request to your follow API endpoint. Revert to "Follow" if the API call fails — the same optimistic update pattern as the social post card like button.
GitHub-style profile integration
For a developer portfolio using real GitHub data: fetch the GitHub GraphQL API with your personal access token to get contribution calendar data. Map the contributionCalendar weeks array to the heatmap grid. The contributionsByDay values map directly to colour intensity levels. Update the streak and total contribution counts from the API response summary fields.
The activity heatmap
The contribution heatmap is a 52-week × 7-day grid of small squares. Each square corresponds to one day. The colour intensity (from light grey to deep indigo) represents activity count on that day — 0 activity is the lightest; maximum activity is the darkest. JavaScript generates the grid using nested loops: for each week (column), create 7 day squares and append to the grid container. Random or real activity data determines each square's colour class.
The circular progress rings
Multiple SVG progress rings use the stroke-dashoffset technique to show different skill or metric percentages. Each ring has a different radius, colour, and target value. The rings animate simultaneously when the component mounts or scrolls into view. See the SVG Progress Ring snippet in this library for the full mathematics explanation.
The follow button state
The follow button toggles between "Follow" and "Following" states using a CSS class and a click handler. The button border and text colour change on toggle. In a real app, the click triggers a POST request to your follow API endpoint. Revert to "Follow" if the API call fails — the same optimistic update pattern as the social post card like button.
GitHub-style profile integration
For a developer portfolio using real GitHub data: fetch the GitHub GraphQL API with your personal access token to get contribution calendar data. Map the contributionCalendar weeks array to the heatmap grid. The contributionsByDay values map directly to colour intensity levels. Update the streak and total contribution counts from the API response summary fields.
Build with AI
Build, Understand, Optimize, and Extend It With AI
Instead of tracing the heatmap loop by hand, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the nested for loops build the 12-column by 7-row grid of divs and assign each cell a random color from the levels array, and whether flexbox with flex-wrap is really the right layout choice compared to CSS grid for a fixed-size matrix like this. It's also worth an optimization question — ask whether creating 84 individual DOM elements via appendChild in a loop causes any noticeable layout thrashing, and how batching with a document fragment would change that. For extending it, have it replace the random data with a real activity count array and map counts to color levels, add hover tooltips showing the date and count per cell, or wire the whole card up to the GitHub GraphQL contributions API. 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:
Build a GitHub-style user stats card with an activity contribution heatmap, in plain HTML, CSS, and vanilla JavaScript with no libraries and no canvas.
Requirements:
- A profile card showing an avatar with initials, a name, a handle, a bio line, a follow button, and a row of four stat tiles (e.g. projects, followers, following, rating).
- A contribution heatmap built entirely from DOM div elements, not an image or canvas: use a nested loop to create a fixed number of columns (representing weeks), and within each column create a fixed number of row cells (representing days), appending each cell to its column and each column to the grid container.
- Each heatmap cell's background color must be selected from a small ordered array of color levels running from a neutral "no activity" shade up through several increasingly saturated shades, so the array itself functions as an intensity scale.
- Lay the columns out with flexbox so the grid reads left to right as weeks progressing through time, with each column stacking its day cells vertically.
- A skills section listing several skill tags as small pill-shaped badges plus a "+N more" indicator.
- A follow button that toggles between an outlined "Follow" state and a filled "Following" state on click, changing its border and background color accordingly.Step by step
How to Use
- 1Load the snippetClick "User Stats Card" in the sidebar. The preview shows the profile card with heatmap, progress ring, and stats.
- 2Update user infoIn the HTML panel, change the avatar initials, username, handle, and bio text.
- 3Update heatmap dataIn the JS panel, change the levels array colours and the random generation logic to reflect real contribution data.
- 4Change progress ring percentageUpdate the data-pct attribute on the SVG .fill circle to your target percentage.
- 5Update follower statsChange the stat numbers (followers, following, repos) in the HTML stats row.
- 6Export 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
Got questions?
Frequently Asked Questions
A JS loop creates 12 columns × 7 rows of divs. Each div gets a random background colour from the levels array (6 shades from grey to deep blue). The grid uses CSS flexbox with flex-wrap to arrange them in a grid pattern.
It uses SVG stroke-dashoffset: CIRCUMFERENCE * (1 - pct/100). The ring starts at full offset (hidden) and animates to the target offset. This is identical to the SVG Progress Ring snippet technique.
Yes. Replace Math.random() with your actual contribution counts. Map the count to a level index: Math.min(5, Math.floor(count / maxCount * 5)). Apply the corresponding level colour.
Update the levels array with your colour scale. The array goes from least active (index 0) to most active (index 5). Any 6-colour scale works.
Yes. Click "JSX" for a React component. Render the heatmap by mapping a 2D data array to div elements. Pass activity data as props.
Add a title attribute to each heatmap div: div.title = date + ": " + count + " contributions". The browser renders a native tooltip on hover.