51 Tailwind CSS Buttons

41 Pure Tailwind10 Tailwind + JSPublished

51 Tailwind CSS buttons for form submits and gradient CTAs, add-to-cart and download actions, loading and confirm-delete states, segmented button groups, and icon toolbars — from soft-pill SaaS primaries and neon plasma bursts to skeuomorphic clay, brushed brass, walnut, velvet, boarding-pass, and punch-card surfaces. Scoped under .tb-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

Related25 CSS Button Groups20 Tailwind SVG Stroke Buttons34 CSS Floating Buttons20 CSS Loading Buttons28 CSS Close Buttons28 Tailwind CSS Close Buttons

Premium upgradePartner: Untitled UI

Affiliate link

Building a whole Tailwind app, not just this component?

You just browsed 51 Tailwind buttons. Untitled UI Pro unlocks 5,000+ components and sections and 250+ page examples for React, styled with Tailwind CSS v4. One licence is a one-time $349 with lifetime updates; teams start at $999.

Get Untitled UI Pro

Untitled UI React. We may earn a commission, at no extra cost to you.

01. Tailwind Submit Button (Form Primary) (opens in a new tab)

Published

Pure Tailwind
The button every form ends with, ported: a two-layer elevation shadow that reads as physical depth, a masked sheen that sweeps once on hover, a real 1px press travel, and a focus ring that survives on any background. The port's win is that all four states now sit in one class list — hover:, active:, focus-visible: and disabled: read in the order a user meets them.

02. Tailwind Primary and Secondary Button Pair (opens in a new tab)

Published

Pure Tailwind
One shared recipe, two visual weights, and a container that stacks them when the slot is narrow — not when the viewport is. The port is the honest test of "utilities can't do variants": they can, and the shared part stays literally identical because both buttons carry the same twenty classes and differ in four.

03. Tailwind Ghost / Outline Button (opens in a new tab)

Published

Pure Tailwind
A ghost button that keeps its 1px silhouette at rest and fills from the bottom edge on hover, the label inverting in the same beat. The fill is one background-size transition on a fixed gradient — no pseudo-element, no overflow clipping — and the border is currentColor, so one colour utility re-skins the whole control.

04. Tailwind Icon-Only Button with Accessible Tooltip (opens in a new tab)

Published

Pure Tailwind
A four-button icon toolbar where each control carries a real accessible name, a 44px touch target inside a 40px visual square, and a tooltip that appears on hover and keyboard focus. has-hover: and has-focus-visible: on the wrapper are the port's headline: the relational CSS selector becomes two variants sitting on the element that owns the tooltip.

05. Tailwind Gradient CTA Button (opens in a new tab)

Published

Pure Tailwind
A conversion-grade CTA with a conic gradient ring that rotates continuously, a soft bloom underneath, and a mesh body that shifts on hover. The rotation needs @property to register the angle as an <angle>, which is the clearest case in the collection for keeping machinery in the stylesheet and exposing only the result as animate-tb05-spin.

06. Tailwind Loading Spinner Button (State Transition) (opens in a new tab)

Published

Tailwind + JS
Idle → pending → success in a button that never changes width, because all three labels share one grid cell. The port's headline is group-data-[state=busy]:: the CSS version needed three descendant selectors keyed off [data-state], and Tailwind states each slot's own visibility condition on the slot itself.
Newsletter

Enjoying these demos? Get new ones by email.

A short email when a new collection ships. Unsubscribe any time.

at

Almost there: check your inbox to confirm.Manage

08. Tailwind Button Group Component (Segmented Radio-Like) (opens in a new tab)

Published

Pure Tailwind
A segmented control on real radio inputs, so arrow-key navigation, roving focus and form serialisation come from the platform. The sliding thumb tracks the checked segment, and the port makes the label's own inversion a has-checked: variant — the state is read where it is rendered, not from four rules at the bottom of a stylesheet.

09. Tailwind Add to Cart Button (opens in a new tab)

Published

Tailwind + JS
The most-measured button in e-commerce: press it and a cart glyph arcs into a badge, the digit bumps, and the label swaps to "Added" before returning to idle — with the real count announced politely, so screen-reader users hear the outcome instead of watching it.

10. Tailwind Download Progress Button (opens in a new tab)

Published

Tailwind + JS
A download button that becomes its own progress bar: the fill sweeps behind the label, a conic ring mirrors it on the icon, and the percentage is a registered custom property so the digits interpolate instead of stepping. One variable drives three visuals — which is exactly the case where Tailwind's job is to expose the variable, not to own it.

11. Tailwind Like Heart Button (opens in a new tab)

Published

Pure Tailwind
A like button with a springy heart pop, eight radial sparks and a count that rolls over — no JavaScript. State lives in a checkbox, and has-checked: turns every downstream reaction into a variant on the element that reacts.

12. Tailwind Confirm Delete Button (opens in a new tab)

Published

Pure Tailwind
A destructive action that asks once, inline, without a modal: the row expands to reveal "Sure? / Yes, delete" with the confirm deliberately placed second and never under the original cursor. The 0fr → 1fr grid-track animation ports to two utilities, which is the cleanest possible expression of it.

13. Tailwind Play Pause Button (opens in a new tab)

Published

Pure Tailwind
One shape that morphs between a play triangle and two pause bars — no icon swap, no SVG. Both states are clip-path: polygon() with matching point counts, and Tailwind carries them as arbitrary utilities, which puts the play polygon and the pause polygon on the same line of markup for the first time.

14. Tailwind Subscribe Confetti Button (opens in a new tab)

Published

Pure Tailwind
Subscribe once and eighteen paper shards fan out on individual trajectories, the bell rings, and the label flips to "Subscribed". Every particle's angle, distance, spin and delay is a custom property in its style attribute — the one place where inline style beats a utility, and the port says so.
Newsletter

Enjoying these demos? Get new ones by email.

A short email when a new collection ships. Unsubscribe any time.

at

Almost there: check your inbox to confirm.Manage

15. Tailwind Magnetic Mercury Ripple Button (opens in a new tab)

Published

Tailwind + JS
The button leans toward your cursor like it is magnetised, a mercury highlight tracks the pointer across its surface, and clicks ripple from the exact point of contact. The JS writes four custom properties; every visual is a utility that reads them — the cleanest division of labour in the collection.

16. Tailwind Brutalist Glitch Button (opens in a new tab)

Published

Pure Tailwind
Neo-brutalist slab with a hard offset shadow that snaps flat when pressed, and a hover glitch built from two duplicate labels sliced by clip-path and pushed apart in cyan and magenta. Steps-based timing keeps it digital — no easing, no blur, no JavaScript.

17. Tailwind Neon Plasma Burst Button (opens in a new tab)

Published

Pure Tailwind
A neon tube that idles at low current, floods with plasma on hover, and fires an expanding shock ring on press. The glow is layered text-shadow and box-shadow rather than a blur filter, so it stays crisp at any zoom — and both stacks are single arbitrary utilities, because a glow is one recipe, not six values.

18. Tailwind Clay Press Button (opens in a new tab)

Published

Pure Tailwind
Fat, matte, extruded clay: two inner shadows carve the highlight and the shade, an outer shadow grounds it, and pressing squashes the shape on both axes so it deforms like real material. The shadows swap direction on press — the whole demo is one shadow-[…] and its active: twin.

19. Tailwind Editorial Ink Spread Button (opens in a new tab)

Published

Pure Tailwind
Letterpress restraint: a serif label on cream stock, a hairline rule that grows into a full underline, and an ink blot that floods from the baseline with a soft irregular edge. The feathered mask is the whole effect and stays one arbitrary value — feathering is a recipe, not a design token.

20. Tailwind Particle Shard Burst Button (opens in a new tab)

Published

Tailwind + JS
Every press shatters a ring of glass shards outward, each with its own angle, distance, spin and lifetime — spawned as real elements, animated by one keyframe, and removed on animationend so the DOM never grows. The shard's look is a class list the JS applies; its trajectory is inline data.

21. Tailwind Brushed Brass Plate Button (opens in a new tab)

Published

Pure Tailwind
A machined brass nameplate: horizontal brush grain from stacked repeating gradients, four countersunk screws, engraved letterforms cut with a two-shadow bevel, and a specular band that sweeps across the metal on hover. The grain is the collection's first clear case for keeping paint in CSS.

22. Tailwind Washi Paper Crane Button (opens in a new tab)

Published

Pure Tailwind
Handmade washi stock with fibrous speckle, a deckled bottom edge cut by a mask, and a folded paper crane whose wing lifts on hover. The button tilts on its long axis like a sheet being picked up — and the two-layer mask that tears the edge is the part that stays CSS.
Newsletter

Enjoying these demos? Get new ones by email.

A short email when a new collection ships. Unsubscribe any time.

at

Almost there: check your inbox to confirm.Manage

23. Tailwind Frosted Ice Cube Button (opens in a new tab)

Published

Pure Tailwind
Real frosted glass over a photograph: backdrop-blur and backdrop-saturate handle the refraction, a bright inner rim catches the light on two edges only, frost collects in the corners, and pressing sends a hairline crack across the face.

27. Tailwind Aged Copper Coin Button (opens in a new tab)

Published

Pure Tailwind
A struck copper coin with a milled edge, verdigris patina blooming in the low spots, and a real 3D flip to its reverse face. v4 ships transform-3d, backface-hidden, perspective-* and rotate-y-* as utilities, so the entire flip construction ports — which it could not have done in v3.

31. Tailwind Mercury Bead Morph Button (opens in a new tab)

Published

Pure Tailwind
A bead of mercury detaches from the button, stretches, and is reabsorbed on hover — genuine metaball merging from an SVG goo filter applied to plain CSS shapes. The filter is markup, the geometry is utilities, and the label sits outside the filtered layer so it stays sharp.

33. Tailwind Masking Tape Label Button (opens in a new tab)

Published

Pure Tailwind
A strip of drafting tape stuck slightly crooked: translucent so the surface shows through, fibrous weave running lengthwise, ragged torn ends cut by a repeating mask, and a hand-written label. Hover presses the tape flatter; pressing sticks it down.

36. Tailwind LED Segment Display Button (opens in a new tab)

Published

Tailwind + JS
A machined instrument panel with a real seven-segment readout: every digit is seven CSS bars lit from a lookup table, glowing with a layered bloom against a smoked lens. Press it and the counter ticks up with correct segment-by-segment switching.

40. Tailwind Polaroid Snapshot Button (opens in a new tab)

Published

Pure Tailwind
An instant photo mid-development: the image starts dark, flat and green-shifted, then blooms to full colour as you hover — a pure filter transition, exactly how the chemistry behaves. The frame tilts, lifts off the table, and the caption is hand-written on the wide bottom border.

41. Tailwind Airline Boarding Pass Button (opens in a new tab)

Published

Pure Tailwind
A boarding pass with a genuinely perforated seam: a mask punches half-circles down the divide, the stub tears away and rotates on hover, and a barcode is drawn with one repeating gradient. Flight numbers use tabular-nums so nothing shifts as they change.

45. Tailwind Regal Postage Stamp Button (opens in a new tab)

Published

Pure Tailwind
A commemorative stamp with true perforations on all four edges, an engraved portrait in sepia, a denomination cartouche, and a postmark that lands across the corner on hover — concentric rings plus a wavy cancellation bar, rotated and off-centre.

47. Tailwind Vintage Calculator Key Button (opens in a new tab)

Published

Pure Tailwind
A 1974 desk calculator key: warm beige ABS with a dished top, a chamfered skirt, tight 3px travel, and the orange function key beside it. The dish is two counter-facing radial gradients, and the press collapses a hard shadow stack so it lands with a stop.

51. Tailwind Brass Periscope Lens Button (opens in a new tab)

Published

Pure Tailwind
A brass periscope objective: a knurled bezel, an engraved focus scale, and a six-blade iris that opens on hover to reveal the glass — each blade a clipped triangle rotating about the optical centre, with a reflection sweep across the coated lens.
FAQ

Frequently asked questions

How does the loading button keep the same width across idle, pending and success states?
The button in demo 06 stacks all three labels — idle text, spinner, success check — into one CSS grid cell using grid-template-areas with every child assigned to the same area. The button's width is therefore fixed by the widest label and never reflows when the state changes. Transitions only touch opacity and visibility, which the compositor handles without a layout pass, so there is no jitter. Drive the state from a single data-state attribute on the button and let attribute selectors reveal the right cell. The common bug is swapping labels with display:none / display:block instead — that collapses the grid cell, so the box snaps narrow on pending and wide again on done. Keep every layer rendered and only fade between them.
How do the confetti and particle-burst buttons animate without any JavaScript?
Demos 14, 20 and 11 pre-render every shard, spark or confetti piece as its own element inside the button, each positioned absolutely and given individual keyframes through inline custom properties like --angle, --dist and --spin. A single keyframe reads those properties in a translate()/rotate() chain, so one shared animation produces dozens of unique trajectories. The burst is triggered by :active (or :focus for keyboard), and the pieces sit in an absolutely-positioned overlay with inset:0 and pointer-events:none so they never change the button's box or intercept clicks. The catch: a pure :active burst only plays while the mouse is held. If you want a fire-and-settle effect on real clicks you either accept the held-state limitation or add a tiny class-toggle in JS — the CSS still does all the motion.
How do I make an icon-only button accessible when there is no visible text label?
The toolbar in demo 04 gives every control a real accessible name with aria-label, so a screen reader announces "Bold", "Italic" and so on even though the face shows only a glyph. The decorative SVG inside each button carries aria-hidden="true" so it is not announced twice. The visible tooltip is purely sighted affordance — it is a separate element revealed on :hover and :focus-visible, never the accessible name, because tooltip text can be clipped or delayed and assistive tech should not depend on it. Each button is a genuine <button type="button"> with a 44px touch target hit area even though the painted size is 40px, satisfying the pointer-target minimum. Don't put the label only in a title attribute: title is inconsistently announced and invisible to touch users.
How does the play/pause button morph between the two icons without swapping SVGs?
Demo 13 uses one element whose shape is defined by clip-path, and the play triangle and the two pause bars are two states of the same polygon. Toggling an aria-pressed attribute (or a checkbox's :checked) switches to a second clip-path value with the same number of points, and because both paths have matching point counts the browser can tween between them. There is no icon library, no image swap and no layout change — only the clip geometry animates. The subtlety is that clip-path interpolation requires identical vertex counts on both keyframes; if one shape has five points and the other has four, the transition snaps instead of morphing. Author both states as the same polygon topology and move the vertices, and expose the current state with aria-pressed so the control is announced as a toggle, not a plain button.
The rotating gradient ring on my CTA button won't animate — why is it stuck?
The conic ring in demo 05 rotates by animating a custom property that holds an angle, and a plain CSS variable cannot be tweened — the browser treats it as a discrete string and jumps straight to the end value, so the ring looks frozen or teleports. The fix is to register the property with @property and declare syntax: '<angle>' plus an initial value; only then does the engine know how to interpolate it, and the conic gradient sweeps smoothly. Also make sure the animated angle feeds the gradient's from position and that the element actually has a size — a zero-height pseudo-element paints nothing. Because this runs continuously it must be wrapped in a @media (prefers-reduced-motion: reduce) block that sets animation: none, otherwise you ship a perpetually spinning element to users who asked the system to stop motion.
How does the segmented button group work on real radio inputs instead of custom state?
Demo 08 builds the segmented control from a group of visually-hidden <input type="radio"> elements sharing one name, each paired with a <label> that is the visible segment. This buys you three behaviours for free: arrow-key navigation and roving focus within the group, a single serialisable value when the control sits in a <form>, and the selected pill styled purely with the :checked sibling selector. Don't hide the inputs with display:none — that removes them from the tab order and kills keyboard support; use a clip/opacity technique that keeps them focusable, and add a :focus-visible ring on the adjacent label so keyboard users can see where they are. Because the state lives in the radios, the group works with no JavaScript and submits like any other field.
What is the difference between the disabled and aria-disabled states in the state-reference button?
Demo 07 shows both because they are not interchangeable. A truly disabled button is removed from the tab order, fires no click or focus events, and cannot be the target of a form submit — the browser enforces all of that. An aria-disabled="true" button still receives focus and still fires events; it only announces as unavailable, and you must block the action in your handler yourself. Use real disabled for a control that is genuinely inert. Reach for aria-disabled when you want the button to stay focusable so a keyboard user can land on it and hear why it can't be used — for example a submit button that is greyed until a form validates, where a fully disabled button would be silently skipped and leave the user confused about what is blocking them. Style both with the same dimmed treatment so they read identically.
When should I not use the heavier tactile buttons like the frosted glass, 3D coin flip or magnetic follow ones?
The material demos — frosted ice (23) with backdrop-blur, the copper coin (27) and punch card (50) with 3D transform, the magnetic mercury (15) tracking the pointer — are showpieces, not defaults. Skip them for high-frequency, high-stakes controls: a checkout's primary submit or an add-to-cart should be instantly legible, and backdrop-blur is one of the more expensive paints on mobile, so a grid of frosted buttons can drop frames. The pointer-following and mercury effects rely on hover and fine pointer movement, so they degrade on touch — always ship a clean fallback state. And every continuously-animated variant (the conic ring, neon idle, spinning reels) must honour prefers-reduced-motion. For dense forms and toolbars prefer the plain primary, ghost or soft-pill buttons (demos 01–03, 32); save the tactile pieces for hero moments where one button carries the page.

Related collections

15 CSS 3D Tilt Hover Cards preview

15 CSS 3D Tilt Hover Cards

15 mouse-aware 3D tilt hover cards — e-commerce product spotlight, glassmorphism parallax team card, interactive pricing tier, holographic NFT collectible, pop-out mascot, dark tech grid with border glow, media player album art, blog article preview, cyberpunk neon glow, dashboard KPI widget, minimalist real estate, flip-to-back tilt, mobile app showcase, course learning card, and a Pure CSS touch-friendly tilt. Vanilla JS writes --rx/--ry/--mx/--my; all rendering stays in CSS on the GPU.

24 CSS Animated Cards preview

24 CSS Animated Cards

24 hand-coded CSS animated card patterns organised by what triggers the motion, not by card style. Scroll and entrance triggers: staggered grid reveals, @starting-style mount-in, scroll-driven scale and fade on animation-timeline: view(), View Transitions API card-to-detail morphs, blur-to-sharp lazy image loading, and FLIP re-layout when a filter changes. State-change triggers: add-to-cart success morph, like and save particle burst, expand and collapse to intrinsic height with calc-size(), swipe-to-dismiss on Pointer Events, and skeleton-to-loaded crossfade. Data-driven triggers: count-up KPI metrics, SVG sparkline draw-on-enter, and progress ring fill on load. Ambient idle loops: breathing glow, floating drift, animated gradient mesh backgrounds, conic rotating borders, auto-cycling testimonial decks, and live status pulses. Plus four hover patterns where the effect is the topic itself: cursor spotlight, holographic foil glare, corner ribbon slide, and horizontal accordion expand. Every card is scoped under a .ac-NN prefix for no-collision pasting, guards prefers-reduced-motion, animates compositor-only properties, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.

22 CSS Avatars preview

22 CSS Avatars

22 hand-coded CSS avatars for chat apps, team dashboards, comment threads, account menus, and social profiles. Covers circular and squircle shapes, gradient and conic story rings, hexagon clip-path crops, online status dots, notification count badges, verified checkmarks, stacked facepiles with plus-N overflow, initials fallbacks for users without photos, broken-image recovery, avatar pickers, and a size scale system where the ring, badge, and status dot all scale from a single custom property.

Search CodeFronts

Loading…