webdevpuneet.com

Fundraising Campaign Leaderboard — Free Ranked Donor Table HTML CSS JS

Fundraising Campaign Leaderboard · Dashboards · Plain HTML, CSS & JS · Live preview

CategoryDashboards

Copy & paste

Source Code

<div class="cl-card">
  <div class="cl-header">
    <h3>Top Fundraisers</h3>
    <span class="cl-period">Spring Gala 2026</span>
  </div>
  <ol class="cl-list" id="clList"></ol>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), 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

Auto-ranked list
A single sort by amount derives every row's rank — no manual numbering.
Leader-relative progress bars
Each bar shows proximity to first place, not a fixed campaign goal.
Top-three medal treatment
data-rank attribute selectors apply gold/silver/bronze accents via CSS.
Initials avatars
Colored circles generated from names — no image assets required.
Overflow-safe rows
Long names truncate with an ellipsis instead of breaking the grid layout.
Locale-formatted amounts
toLocaleString adds thousands separators to every dollar figure.
Semantic ordered list
Built on <ol> so the ranking is meaningful to assistive tech, not just visual.
Data-driven rendering
Edit one array to reflect any campaign's real fundraisers.

About this UI Snippet

Fundraising Campaign Leaderboard — Ranked Rows With Relative Progress Bars

Screenshot of the Fundraising Campaign Leaderboard snippet rendered live

A fundraising campaign leaderboard does two jobs at once: it ranks people, and it shows *how much* separates them, not just the order. This snippet builds that as a ranked list where every row carries a small progress bar scaled relative to the top fundraiser, plus subtle medal-color treatment for the top three — in plain HTML, CSS, and vanilla JavaScript.

Sort once, derive everything from it

The raw DATA array is unsorted; a single .sort() by amount descending produces sorted, and every row's rank is just its index + 1. This keeps the source data easy to edit — add a fundraiser anywhere in the array — without ever having to manually recompute rank numbers.

Progress bars relative to the leader, not to a fixed goal

Each row's bar width is amount / top × 100, where top is the highest fundraiser's total — not a percentage of some external campaign goal. That's a deliberate choice: it makes the visual comparison read as "how close is this person to first place," which is the competitive framing a leaderboard is for for, distinct from a donation thermometer's goal-relative fill.

Medal color without medal icons

Rather than trophy emoji, rank 1–3 get a data-driven data-rank attribute that CSS attribute selectors key off of — gold, silver, and bronze tints applied to the rank number and that row's own progress-bar gradient, plus a faint background wash on .cl-top rows. It's a restrained way to signal "these three matter most" that still reads correctly in a dense list.

Initials avatars, no image dependency

Each row gets a colored circular avatar built from the fundraiser's initials and a color cycled from a fixed palette — so the component works with zero image assets or network requests, useful for a demo, a placeholder state, or any fundraiser without a photo on file.

Overflow-safe names

Names use white-space: nowrap with text-overflow: ellipsis inside a min-width: 0 flex child, so a long name truncates cleanly instead of breaking the row's grid layout — a detail that matters once the list holds real, unpredictable names.

Customizing it

Swap DATA for your live campaign totals, add avatar photos in place of the initials circles, or extend rows with a "view profile" link. Pair it with a leaderboard table for a denser variant or leaderboard podium to spotlight just the top three.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA ranked leaderboard renders, sorted by amount raised, high to low.
  2. 2
    Check the top threeRanks 1–3 get gold, silver, and bronze accents on the number and bar.
  3. 3
    Compare the barsEach bar's width shows that person's total relative to the leader, not a fixed goal.
  4. 4
    Edit DATAAdd, remove, or update fundraiser names and amounts — rank recalculates automatically.
  5. 5
    Swap avatar colorsAdjust AVATAR_COLORS or replace initials circles with real photos.
  6. 6
    Connect live totalsRe-run the render whenever fundraising data updates from your backend.

Real-world uses

Common Use Cases

Peer-to-peer fundraising
Rank top individual fundraisers, with each row's bar scaled to the leader so people see how close they are to first place, not just their order.
Team fundraising drives
Swap individuals for teams in the same ranked layout, with data-rank attribute selectors giving the top three gold, silver and bronze treatment.
Sales and referral contests
Run an internal contest board, with one sort by amount deriving every row's rank so no number is ever hand-edited.
School and alumni giving pages
Pair with a donation thermometer to show the overall campaign total beside the individual leaders on a school or alumni giving page.
Community challenge dashboards
Combine with a live visitor counter for a lively event page, and see the leaderboard table for sortable columns.
Related: Consistent Hashing Visualizer
See the Consistent Hashing Visualizer for a related dashboards pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

A single Array.sort() call on the raw DATA array, comparing amount descending, produces the sorted list once; each row's rank is simply its position in that sorted array plus one. There is no separate rank field to keep in sync — add or edit a fundraiser in DATA and the ranking recalculates correctly on the next render.

A leaderboard's purpose is competitive comparison — how close is each person to first place — which is different from a campaign thermometer showing progress toward an external dollar goal. Dividing every amount by the top fundraiser's total keeps the bars meaningful as a head-to-head comparison regardless of what the campaign's overall goal is.

Each row carries a data-rank attribute set to its numeric rank, and CSS attribute selectors like .cl-row[data-rank="1"] apply gold, silver, or bronze tints to that row\'s rank number and progress-bar gradient. Ranks below three simply do not match those selectors and fall back to the default indigo styling.

The name sits in a flex child with min-width: 0, and the name element itself uses white-space: nowrap with text-overflow: ellipsis, so a long name truncates with an ellipsis rather than wrapping or pushing the amount out of the row. The min-width: 0 is essential — without it, flex children refuse to shrink below their content's natural width and the truncation would not take effect.

Keep the sort-then-map logic as a derived/computed value from your data source — useMemo in React, a computed() in Vue, or a getter in Angular — so the sorted list and each row\'s relative-progress percentage recalculate automatically whenever the underlying fundraiser data changes. The row markup and CSS port unchanged.