More Cards Snippets
Referral Card — Invite & Earn HTML CSS JS Snippet
Referral Card · Cards · Plain HTML, CSS & JS · Live preview
What's included
Features
copyLink uses navigator.clipboard.writeText (with an https:// prefix) and confirms "Copied ✓" for 1.6s — frictionless sharing.scaleX from a left origin with a transform transition — smooth and export-safe across frameworks.cubic-bezier scale pop, rewarding the action.invited and GOAL drive render/renderAvatars, so seeding real data is a couple of assignments.About this UI Snippet
Referral Card — Copyable Link, Avatar Milestone Progress & Reward Unlock

Referral programmes are among the most cost-effective growth channels, and the referral card is where users grab their link and watch their rewards build. A good one does three things: makes the referral link trivially copyable, shows clear progress toward a reward milestone, and celebrates when the reward unlocks. This snippet implements all three in plain HTML, CSS, and vanilla JavaScript: a copy-with-feedback referral link, an avatar progress row, an animated progress bar toward a goal, and a reward-unlocked state.
Frictionless link copy
The referral URL sits in a dashed "ticket" field with a Copy button. copyLink uses the modern navigator.clipboard.writeText API (prefixing https:// so the copied link is complete) and confirms with "Copied ✓" in green for 1.6 seconds before resetting. Removing every bit of friction from grabbing the link directly affects how many people share — so the copy interaction is the most important part of the card.
Avatar milestone progress
Progress toward the reward is shown two ways. A row of avatar slots — filled gradient circles for friends who joined, dashed "+" placeholders for the remaining — gives a tangible, human sense of "3 of 5". Below it, a progress bar fills proportionally. The bar uses transform: scaleX from a left origin with a transition: transform, so it animates smoothly and, being a transform, exports cleanly to utility frameworks (which animate transforms but not raw width).
Reward goal and unlock
The status line shows "3 of 5 friends joined" and the reward chip teases "$50 bonus at 5". The demo "Send an invite" button increments the count: each invite fills the next avatar with a spring pop, advances the bar, and updates the status. On reaching the goal, render switches the card to a complete state — the bar turns green, the chip becomes "$50 unlocked 🎉", and the button locks to "Reward unlocked ✓". That payoff moment is what makes the mechanic rewarding.
Driven by simple state
Everything derives from two values, invited and GOAL, through render and renderAvatars, so wiring it to real data is just seeding invited from your backend and replacing the demo button with the actual share/send flow. The card's premium dark styling with a radial glow gives the reward the elevated feel referral programmes rely on.
Pair this with a social share bar for sharing the link across networks, a loyalty points widget for the rewards balance, or a copy button pattern elsewhere.
Build with AI
Build, Understand, Optimize, and Extend It With AI
You do not need to work through the state model here on your own. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why the progress bar animates with a scaleX transform from a left transform-origin instead of animating the width property directly, and why that specific choice matters when this snippet gets converted into a Tailwind export. The same assistant can help optimize it — ask whether renderAvatars() rebuilding the entire avatar row's innerHTML on every single invite is necessary versus updating just the one newly-filled avatar element directly. It's also useful for extending the card: ask it to add a countdown showing days left in the referral promotion, wire sendInvite to the real Web Share API on mobile with a clipboard fallback on desktop, or support a multi-tier reward structure where the chip text and unlock state change at several milestones instead of just one. 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 referral/invite progress card in plain HTML, CSS, and JavaScript with no library.
Requirements:
- Show a copyable referral link inside a dashed "ticket" field with a Copy button that uses the navigator.clipboard.writeText API, falling back gracefully if that API is unavailable, and shows a temporary "Copied" confirmation state on the button for about 1.5 seconds before reverting.
- Render a row of avatar placeholder circles equal to a fixed goal count: circles up to the current invited count must show a filled gradient style, and the remaining circles must show an empty dashed placeholder style.
- Render a progress bar whose fill element is animated using a CSS transform of scaleX (with transform-origin set to the left edge) rather than animating the width property directly, scaled to invited count divided by goal count.
- Every time a new invite is registered, the newly-filled avatar circle must play a distinct spring/pop scale-in animation (going from scale 0 to scale 1 with an overshooting easing curve) so the moment of progress feels rewarded, not just silently updated.
- When the invited count reaches the goal, switch the whole card into a distinct "complete" visual state: the progress bar and reward text change color to a success color, the reward chip text changes to an unlocked message, and the invite button becomes disabled with different label text.
- Drive the entire UI from exactly two state values (the current invited count and the fixed goal count) through render functions, so seeding real backend data requires only assigning those two values before the first render.Step by step
How to Use
- 1Paste HTML, CSS, and JSA "Give $10, get $10" referral card appears with a copyable link, an avatar row (3 filled, 2 empty), a progress bar, and an invite button.
- 2Copy the linkClick Copy — the referral URL is copied to the clipboard and the button confirms "Copied ✓" in green.
- 3Send an inviteClick "Send an invite" — the next avatar fills with a spring pop, the bar advances, and the status updates to "4 of 5".
- 4Reach the goalInvite the fifth friend — the bar turns green, the chip reads "$50 unlocked 🎉", and the button locks to "Reward unlocked ✓".
- 5Read the milestoneThe reward chip always shows the next milestone so users know what they are working toward.
- 6Wire real dataSeed
invitedfrom your backend and replace the demo button with your real share/send flow; the card recomputes.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Generate a unique code per user server-side (tie it to their account) and render it into the URL. Track signups by reading the ?ref= param on registration and crediting the referrer. Seed invited from the count of successful referrals, and award the reward server-side when the goal is reached — never trust the client for the actual payout.
On mobile, use the Web Share API: a "Share" button that calls navigator.share({ title, url }) opens the OS share sheet (Messages, WhatsApp, email). Fall back to the copy button and a social share bar of intent links on desktop. Sharing directly converts better than copy-then-paste.
transform: scaleX runs on the compositor for smoothness and, importantly for this site's exports, Tailwind's transition utility animates transforms but not raw width — so a width-based bar would snap in the React + Tailwind build. Scaling from a left origin gives the same visual fill while staying export-safe.
Make the copy and invite controls real <button>s (they are) so they are keyboard-operable, and announce the copy success and progress changes via an aria-live="polite" region. Give the progress bar role="progressbar" with aria-valuenow/aria-valuemax, and ensure the reward state is conveyed in text, not colour alone.
In React, hold invited (and the link) in useState, derive the bar scale and avatars from it, and manage the "Copied" flag with a setTimeout. In Vue, use refs and a computed for progress with v-for avatars. In Angular, track state on the component and bind [style.transform]. The scaleX bar and pop keyframe port unchanged.