20 CSS Copy Buttons

20 hand-coded CSS copy buttons for documentation sites, dashboards, checkout pages and share flows. Covers the checkmark success state, icon-morph animation, the Clipboard API with a working fallback for insecure contexts, buttons embedded in inputs and code blocks, masked API keys, coupon codes and truncated wallet addresses that copy the full value. Includes the ARIA live region most builds skip and the one-handler pattern for many buttons on a page. Scoped under .cpy-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

1 pure CSS19 light JSPublished

Related20 CSS Code Blocks30 CSS Notifications21 CSS Tooltips20 CSS Social Buttons

CSS Copy to Clipboard Button with Success Checkmark State — preview
01 / 20Light JS

CSS Copy to Clipboard Button with Success Checkmark State

The reference build for the whole collection: a copy button that reads Copy, flips to Copied! with a checkmark, and reverts after two seconds. Icon and label crossfade in the same 200 ms, the width never jumps because both labels are stacked in one grid cell, and the success is announced to screen readers as well as shown. Every other demo is a variation on this state machine.

Published

CSS Copy Button Icon Morphing Animation (Copy to Checkmark) — preview
02 / 20Light JS

CSS Copy Button Icon Morphing Animation (Copy to Checkmark)

The icon itself is the feedback. On copy, the clipboard glyph shrinks and rotates out while a checkmark draws itself with stroke-dashoffset, then the whole thing rewinds on reset. A duration switcher (150 / 220 / 380 ms) lets you feel exactly where a micro-interaction stops reading as instant — and it is pure CSS, driven by :has() on three radios.

Published

CSS Copy Button with Tooltip Feedback — preview
03 / 20Light JS

CSS Copy Button with Tooltip Feedback

A tooltip that does two jobs: it explains the button before the click (Copy to clipboard) and confirms it after (Copied to clipboard!). It opens on hover and on :focus-visible, so keyboard users get the same hint, and stays pinned for two seconds after a successful copy even when the pointer has already left.

Published

CSS Pure Copy Button Visual Effect with HTML5 Checkbox Hack — preview
04 / 20Pure CSS

CSS Pure Copy Button Visual Effect with HTML5 Checkbox Hack

The zero-JavaScript version of the copy interaction — and an honest one. A hidden checkbox plus :checked drives the entire Copy → Copied! state change, including the checkmark and the tinted surface. What it deliberately does not do is write to the clipboard: no CSS feature can. This demo is the feedback pattern; the write needs the one line of script shown in demo 05.

Published

CSS Clipboard API Copy Button with Fallback — preview
05 / 20Light JS

CSS Clipboard API Copy Button with Fallback

The demo that answers the single most-searched failure in this topic: why is navigator.clipboard undefined? A live environment probe reports secure context, API availability and permission result, the button copies through writeText() and silently falls back to a hidden <textarea> plus execCommand('copy') when it cannot, then tells you which path actually did the work.

Published

CSS Code Block Copy Button Top Right Corner — preview
06 / 20Light JS

CSS Code Block Copy Button Top Right Corner

Placement, offset and hit area — the three things that actually decide whether a code-block copy button feels right. The block here is deliberately plain so the button is the subject: it sits in the top-right corner, the <pre> reserves padding so no line ever runs under it, and a toggle draws the invisible 44 × 44 px target so you can see the difference between a 32 px icon and a real touch target.

Published

CSS Copy Button Inside Input Text Field — preview
07 / 20Light JS

CSS Copy Button Inside Input Text Field

A copy control that lives inside the field's border, on the trailing edge, the way Stripe and Linear do it. The input keeps its own focus ring, the button never covers the text because the field reserves padding for it, and what gets copied is the live value — type something and the button copies what you typed, not a hardcoded string.

Published

CSS Inline Copy Button Beside Paragraph Text — preview
08 / 20Light JS

CSS Inline Copy Button Beside Paragraph Text

A copy control small enough to live inside a sentence. Two of them sit in this paragraph — beside a design token and beside a package name — baseline-aligned so the line height never shifts, hoverable as part of the code span, and each copying its own value. The hard part is not the click handler, it is making a button that does not disturb running text.

Published

CSS Copy Button Reveal on Hover Pattern — preview
09 / 20Light JS

CSS Copy Button Reveal on Hover Pattern

The pattern that keeps a docs page calm: the copy button is invisible until you approach the block, then fades and slides into place in 180 ms. The part almost every implementation gets wrong is the keyboard — a hover-only reveal is a button a keyboard user can focus but never see. Here :focus-within reveals it too, and touch devices get it permanently.

Published

CSS Floating Sticky Copy Button for Long Code Snippets — preview
10 / 20Light JS

CSS Floating Sticky Copy Button for Long Code Snippets

A forty-line snippet in a scrollable container, with a copy button that stays reachable the whole way down. It is position:sticky in a scroll container the block owns — not fixed, which would float over unrelated content — plus the two silent sticky killers spelled out: an ancestor overflow that is not visible, and an ancestor transform.

Published

CSS Masked API Key Input Field with Copy Button — preview
11 / 20Light JS

CSS Masked API Key Input Field with Copy Button

The real dashboard pattern: a secret shown as sk_live_••••••••4a2f, an eye toggle to reveal it, and a copy button that always copies the full key — never the masked display string. The mask is presentation; the value lives in one place and the two controls read from it.

Published

CSS E-commerce Coupon Code Card with Copy Button — preview
12 / 20Light JS

CSS E-commerce Coupon Code Card with Copy Button

A promo card built the way a store actually ships one: product shot, offer, a dashed voucher rail with SAVE20 set large in mono, and a copy button that confirms in place. The ticket notches are pure CSS radial gradients, and the terms line stays honest — the copy button is the payoff, not decoration.

Published

CSS Share Short URL Link Copy Button Input Group — preview
13 / 20Light JS

CSS Share Short URL Link Copy Button Input Group

The share-sheet pattern: a read-only field and a copy button welded into one unit, sharing a border and splitting the radius so it reads as a single control rather than two components pushed together. Focus the field and the whole link selects; press <kbd>Enter</kbd> and it copies — no form submit involved.

Published

CSS Contact Card Email & Phone Number Copy Button — preview
14 / 20Light JS

CSS Contact Card Email & Phone Number Copy Button

A compact profile card where the email and the phone number each carry their own copy control, plus the links themselves — because some people want to copy, and some want mailto:. Two icon buttons, distinct aria-labels, one delegated handler, and a per-row success tick that never disturbs the card's rhythm.

Published

CSS Web3 Wallet Address Copy Button with Text Truncation — preview
15 / 20Light JS

CSS Web3 Wallet Address Copy Button with Text Truncation

A wallet chip showing 0x71C7…976F — truncated by CSS, not by JavaScript — that copies all 42 characters. The full address is in the DOM the whole time, split into a flexible head and a fixed tail so the ellipsis lands in the middle; the clipboard receives the real string, because pasting a shortened address means losing funds.

Published

CSS Copy Button with Animated Toast Notification — preview
16 / 20Light JS

CSS Copy Button with Animated Toast Notification

When the button is far from where the user is looking, the confirmation has to come to them. A minimal toast slides up from the bottom, announces itself politely, and dismisses after 2.4 s — and rapid clicks restart the timer instead of stacking toasts. The toast is intentionally plain: the button is still the subject.

Published

CSS Copy Button Loading, Success, and Error States — preview
17 / 20Light JS

CSS Copy Button Loading, Success, and Error States

Almost every copy button ships two states. This one ships three, including the error case nobody builds: the value has to be fetched before it can be copied, so there is a real loading state, and the write can fail with permission denied, insecure context or nothing to copy. Switch the scenario and watch each path resolve honestly.

Published

CSS Copy Button Feedback Countdown Reset Timer — preview
18 / 20Light JS

CSS Copy Button Feedback Countdown Reset Timer

Most copy buttons revert on an invisible timer, so the user cannot tell whether the state is sticky or about to vanish. This one draws the wait: a countdown ring sweeps around the tick over two seconds, the button ignores clicks while it runs, and the ring restarts cleanly — no stacked timers, no flicker.

Published

CSS Accessible Copy Button with ARIA Live Region — preview
19 / 20Light JS

CSS Accessible Copy Button with ARIA Live Region

A copy button that a screen reader user can actually use: aria-label on the icon-only control, a polite live region that announces Copied to clipboard, a 2 px focus ring you cannot miss, and a 44 × 44 px target. The panel beside it transcribes every announcement as it happens, so you can see exactly what assistive tech hears.

Published

CSS Copy Button Reusable Class for Multiple Code Blocks — preview
20 / 20Light JS

CSS Copy Button Reusable Class for Multiple Code Blocks

The last bug everyone hits: three copy buttons, and every one of them copies the first block. The fix is not three handlers — it is one delegated listener that finds the pressed button with closest() and reads that button's own target from a data-* attribute. Add a fourth row and it works with no new JavaScript.

Published

FAQ

Frequently asked questions

How do I copy text to the clipboard with JavaScript?
One line does the work: await navigator.clipboard.writeText(value). It returns a promise, so wrap it in try/catch and drive your UI from the result rather than assuming success — that single habit is what separates a copy button that works from one that silently lies. The important constraint is that the Clipboard API is only available in a secure context: HTTPS, or localhost during development. On a plain http:// page or a file opened directly from disk, navigator.clipboard is undefined and your handler throws immediately. Check for it before calling — if (navigator.clipboard && window.isSecureContext) — and fall back to the textarea technique below. Write to the clipboard only in direct response to a user gesture like a click; browsers reject clipboard writes from timers or on page load, which is a deliberate anti-abuse measure rather than a bug.
Why is navigator.clipboard undefined or not working?
Almost always the secure-context rule. The Clipboard API is gated on HTTPS, and localhost counts as secure, so a button that works perfectly in local development can fail the moment it ships to a staging box served over plain HTTP. Opening the page as a file:// URL fails the same way, which catches people testing a downloaded snippet by double-clicking it. Inside an iframe there is a second gate: the frame needs clipboard-write permission, so an embedded playground or preview can reject the call even on an HTTPS parent. The fix in every case is the same — feature-detect, then fall back to a hidden textarea plus document.execCommand('copy'), which is deprecated but still works everywhere and needs no permission. Never let the failure be silent: show the user a message telling them to select and copy manually, which is what a screen-reader user needs anyway.
Can you copy to the clipboard with CSS only?
No, and any tutorial claiming otherwise is describing something else. Writing to the clipboard requires a JavaScript API call — CSS has no access to it and never will, because the clipboard is a security-sensitive system resource. What CSS can do is the entire feedback experience: a hidden checkbox plus :checked flips the label from "Copy" to "Copied", swaps the icon, and animates the transition with no script at all. That is genuinely useful for prototyping the interaction or for a design-system reference, and it is what the pure-CSS demo in this collection shows — with the limitation stated on the page rather than implied away. There is one honest half-measure: an <input> or <textarea> with onfocus="this.select()" pre-selects the value so the user only has to press Ctrl+C, which reduces the interaction to one keystroke without any clipboard write.
How do I make a copy button accessible to screen readers?
A copy button that only changes colour is invisible to assistive technology. Three things fix that. Use a real <button type="button"> with an aria-label if the button is icon-only, so it is announced as something activatable rather than skipped. Put the confirmation in a live region — an empty element with aria-live="polite" that you write "Copied to clipboard" into on success — because a visual state change fires no accessibility event on its own. Use role="alert" instead for the failure path, since a copy that did not happen is urgent and the user needs to know to select the text manually. Beyond that, keep a visible :focus-visible ring and a 44×44px minimum target per WCAG 2.5.8; icon-only copy buttons are frequently 24px, which is a real problem on touch. Do not disable the button during the success window without saying why.
How do I position a copy button on a code block?
Absolute positioning inside a relatively-positioned wrapper, offset from the top-right corner: position: absolute; top: .6rem; right: .6rem on the button, position: relative on the <pre>. Two details make it feel right. Give the <pre> enough padding-right that a long first line cannot slide underneath the button — otherwise the button sits on top of the code it is meant to copy. And if you reveal the button only on hover to keep the block clean, add :focus-within to the same rule, or keyboard users can never reach it: .block:hover .copy, .block:focus-within .copy { opacity: 1 }. For a very tall snippet, position: sticky; top: .6rem keeps the button reachable while the reader scrolls through the code, though sticky silently fails if any ancestor has overflow: hidden or a transform.
How do I copy a truncated or masked value correctly?
Keep the display string and the clipboard string separate. This matters most for wallet addresses shown as 0x71C7…8f3A and API keys masked as sk_live_••••4a2f: the visible text is a presentation choice, and copying it gives the user something useless. Store the real value where the handler can reach it — a data-copy-value attribute, a hidden input, or the element's own value if it is a read-only field — and truncate only visually with text-overflow: ellipsis or a CSS-generated middle ellipsis. Never truncate the source string in JavaScript and then copy that. The same rule applies to the masked-key pattern: the mask belongs to the view layer, so the reveal toggle and the copy button both read the underlying value, not the asterisks the user can see.
Why do all my copy buttons copy the same text?
Because one handler is bound to one value instead of reading its own target. The usual shape of the bug is a query for a single element — document.querySelector('.copy-btn') — wired once, or a shared variable captured outside a loop, so whichever value was current at setup time is the one every button copies. Fix it by letting each button carry its own target: <button data-copy-target="#snippet-3">, then one delegated listener on the container reads event.target.closest('[data-copy-target]') and resolves the value per click. That scales to any number of buttons with a single listener, survives content added after page load, and avoids the ID collisions you get from generating id="copy1", id="copy2" and so on. It also keeps the success state local — set it on the clicked button, not on every button sharing the class.
How do these port to React, Vue, Svelte and Tailwind?
The CSS ports unchanged — every .cpy-NN selector and custom property is framework-agnostic. The copy logic is where framework idiom matters, and the shape is the same everywhere: a small async handler plus one piece of state for the success window. In React that is const [copied, setCopied] = useState(false) with a setTimeout to clear it, and the timer must be cleared in the effect's cleanup or a rapid re-click leaves a stale timeout that resets the label early. Vue uses a ref and onBeforeUnmount; Svelte a plain let and onMount's returned cleanup. One React-specific trap: do not put the handler inline in JSX if the component re-renders often, or you create a new function on every render and lose the ability to clear the previous timer. For Tailwind the states map to group plus data-[state=copied]: variants, which keeps the whole feedback transition in markup without a stylesheet.

Related collections

30 CSS Badges preview

30 CSS Badges

30 hand-coded CSS badges for status indicators, notifications, membership tiers, live-data displays, and SEO / DevOps / financial dashboards — upload progress, typing indicator, transit line status, Core Web Vitals, ECG heartbeat, CI/CD build pipeline, countdown ring, live price ticker, keycap shortcut, wax seal, conference lanyard, and holographic collectibles. Copy-paste HTML and CSS, WCAG 2.2 accessible, MIT licensed.

20 CSS Banners & Alerts preview

20 CSS Banners & Alerts

20 hand-coded CSS banner and alert bars for e-commerce storefronts, SaaS dashboards, marketing sites, and compliance-bound products. Covers GDPR cookie consent with a real preferences panel, promo bars with countdown timers, free-shipping threshold progress, app-install smart banners, maintenance and incident status bars, newsletter signup bars, age verification gates, limited-stock urgency banners, live event announcements, browser upgrade notices, geo and currency switchers, sticky top announcement bars, bottom cookie bars, inline form validation alerts, icon-aligned alert banners, left-border accent alerts, diagonal stripe promos, full-width hero banners, animated gradient border alerts, and a text-wrapping laboratory that shows five strategies for the unbreakable string that breaks more banners than anything else. Every bar is scoped under a .ba-NN prefix for no-collision pasting, guards prefers-reduced-motion, carries the correct aria-live and role semantics, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.

25 CSS Blockquotes preview

25 CSS Blockquotes

25 hand-coded CSS blockquote designs for SaaS testimonials, editorial pull quotes, documentation callouts, and developer engineering blogs: large decorative quotation marks with ::before / ::after glyphs, Tailwind CSS blockquote component, pure CSS callout / admonition boxes for Docusaurus / Mintlify / Nextra documentation, responsive center-aligned quote banners, modern minimalist left-border editorial style, animated CSS gradient border, classic left border, brutalist high-contrast, glassmorphism frosted card, glowing neon border, article pull quote with text-wrap, speech bubble chat-style, thick vertical accent rail, customer testimonial cards with avatar and star rating, inline highlighted text, marker highlight underline, floating drop-shadow, aurora gradient background, Twitter / X card style, multi-column newspaper editorial, IDE code-comment style, Markdown-compatible defaults, JavaScript testimonial quote slider, expandable read-more, and one-click copy button. 22 Pure CSS + 3 Light JS (slider, expand, copy). Every design scoped under .bq-NN prefix for no-collision pasting, prefers-reduced-motion guarded per WCAG 2.3.3, WCAG 2.2 AA accessible, framework-agnostic (React, Vue, Svelte, Astro, Next.js, Nuxt, Remix, SvelteKit).

Search CodeFronts

Loading…