SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/tailwind-svg-stroke-buttons

6 Tailwind SVG Stroke Buttons

5 Tailwind1 with JSPublished 2026-10-05Free · no sign-up

Six buttons and links that draw lines with SVG strokes: a border that traces itself, a ring around a play button, a wavy underline, a tick that draws after saving, an arrow shaft that extends and a dashed border that marches.

01. Tailwind Border Draw Button

TailwindSVGStroke

An SVG rectangle traces itself around the button on hover and keyboard focus. pathLength="100" makes the dash maths independent of the button's size, so stroke-dasharray and stroke-dashoffset are simply 100.

View code
<button type="button" class="group relative rounded-xl px-7 py-3 font-semibold text-slate-900 focus-visible:outline-none">
  <svg aria-hidden="true" class="pointer-events-none absolute inset-0 h-full w-full overflow-visible" fill="none" stroke-width="2"><rect width="100%" height="100%" rx="12" class="stroke-slate-300"/><rect width="100%" height="100%" rx="12" pathLength="100" class="stroke-indigo-600 transition-[stroke-dashoffset] duration-700 ease-out [stroke-dasharray:100] [stroke-dashoffset:100] group-hover:[stroke-dashoffset:0] group-focus-visible:[stroke-dashoffset:0] motion-reduce:transition-none"/></svg>
  Start a project
</button>

02. Tailwind Circular Stroke Play Button

TailwindSVGCircle

A round play button whose ring draws clockwise from the top on hover or focus. The SVG is rotated -90 degrees so the stroke starts at twelve o'clock, and the button's accessible name comes from aria-label.

View code
<button type="button" aria-label="Play preview" class="group relative grid size-16 place-items-center rounded-full text-white focus-visible:outline-none">
  <svg aria-hidden="true" viewBox="0 0 64 64" fill="none" stroke-width="3" class="absolute inset-0 -rotate-90"><circle cx="32" cy="32" r="30" class="stroke-white/25"/><circle cx="32" cy="32" r="30" pathLength="100" stroke-linecap="round" class="stroke-cyan-400 transition-[stroke-dashoffset] duration-500 [stroke-dasharray:100] [stroke-dashoffset:100] group-hover:[stroke-dashoffset:0] group-focus-visible:[stroke-dashoffset:0] motion-reduce:transition-none"/></svg>
  <svg aria-hidden="true" viewBox="0 0 24 24" class="relative ml-1 size-6 fill-current"><path d="M7 4v16l13-8z"/></svg>
</button>

03. Tailwind Squiggle Underline Link

TailwindSVGLink

A link whose hand-drawn wavy underline draws itself from left to right on hover or focus. The wave is one SVG path made of repeated quadratic curves, stretched to the width of the link text.

View code
<a href="#story" class="group relative inline-block pb-3 text-xl font-bold text-slate-900 focus-visible:rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-rose-600">Read the story
  <svg aria-hidden="true" viewBox="0 0 196 12" preserveAspectRatio="none" class="absolute bottom-0 left-0 h-3 w-full overflow-visible"><path d="M2 8Q14 2 26 8T50 8T74 8T98 8T122 8T146 8T170 8T194 8" fill="none" stroke-width="3" stroke-linecap="round" pathLength="100" class="stroke-rose-600 transition-[stroke-dashoffset] duration-700 [stroke-dasharray:100] [stroke-dashoffset:100] group-hover:[stroke-dashoffset:0] group-focus-visible:[stroke-dashoffset:0] motion-reduce:transition-none"/></svg>
</a>

04. Tailwind Save Button with Drawn Tick

TailwindSVGFeedback

After a click the button says Saved and a tick draws itself beside the word. A data attribute switches on group-data-[done] utilities, the drawing is a small keyframe animation, and a status message tells screen reader users the save worked.

View code
<button id="twss4" type="button" class="group flex h-12 w-44 items-center justify-center gap-2 rounded-full bg-emerald-700 font-semibold text-white transition-colors hover:bg-emerald-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-emerald-700 data-[done]:bg-teal-700">
  <svg aria-hidden="true" viewBox="0 0 24 24" class="hidden size-5 group-data-[done]:block"><path d="M4 12.5l5 5L20 6.5" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" pathLength="100" class="[stroke-dasharray:100] [stroke-dashoffset:100] motion-safe:group-data-[done]:animate-[twss-draw_.5s_ease-out_forwards] motion-reduce:group-data-[done]:[stroke-dashoffset:0]"/></svg>
  <span>Save changes</span>
</button>
<p id="twss4s" role="status" class="sr-only"></p>
@keyframes twss-draw { to { stroke-dashoffset: 0; } }
var b = document.getElementById('twss4'), t;
b.onclick = function () { b.dataset.done = ''; b.querySelector('span').textContent = 'Saved'; document.getElementById('twss4s').textContent = 'Changes saved'; clearTimeout(t); t = setTimeout(function () { delete b.dataset.done; b.querySelector('span').textContent = 'Save changes'; }, 2500); };

05. Tailwind Extending Arrow Link

TailwindSVGArrow

A text link whose arrow shaft grows out of the arrowhead on hover. The shaft is drawn from right to left, so a partial dash offset leaves a short stub next to the head that extends to full length.

View code
<a href="#next" class="group inline-flex items-center gap-3 rounded-lg px-2 py-1 text-lg font-semibold text-slate-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-amber-300">Next chapter
  <svg aria-hidden="true" viewBox="0 0 48 24" fill="none" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" class="h-6 w-12 stroke-amber-300"><path d="M44 12H2" pathLength="100" class="transition-[stroke-dashoffset] duration-500 [stroke-dasharray:100] [stroke-dashoffset:65] group-hover:[stroke-dashoffset:0] group-focus-visible:[stroke-dashoffset:0] motion-reduce:transition-none"/><path d="M36 5l8 7-8 7"/></svg>
</a>

06. Tailwind Marching Dashed Border

TailwindSVGDashed

A dashed outline whose dashes march around the button while it is hovered, like a selection marquee. A short keyframe moves stroke-dashoffset by one dash-and-gap, so the loop is seamless, and it only runs when motion is allowed.

View code
<button type="button" class="group relative rounded-lg px-6 py-3 font-semibold text-violet-200 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-violet-300">
  <svg aria-hidden="true" class="pointer-events-none absolute inset-0 h-full w-full overflow-visible" fill="none" stroke-width="2"><rect width="100%" height="100%" rx="10" class="stroke-violet-400 [stroke-dasharray:6_6] motion-safe:group-hover:animate-[twss-march_.6s_linear_infinite]"/></svg>
  Upload files
</button>
@keyframes twss-march { to { stroke-dashoffset: -12; } }

About these Tailwind SVG Stroke Buttons

Dash offset draws the line

Set the dash array to the path's length and the offset to the same value, so the stroke is hidden; transitioning the offset to 0 draws it.

pathLength makes it size-proof

With pathLength="100" on the shape, the dash values are always 100, whatever the button's real size.

Arbitrary properties for SVG

Tailwind has stroke colour and width utilities; dash values come from arbitrary properties such as [stroke-dashoffset:100] and transition-[stroke-dashoffset].

Hover and focus together

Pair every group-hover: with group-focus-visible: so keyboard users see the same drawing.

Frequently asked questions

Are the SVGs read by screen readers?

No. They are aria-hidden decoration; the button text or aria-label carries the meaning.

Where do the keyframes go?

In your CSS file or tailwind.config, as shown in the CSS tab.

Is there a CSS version?

Yes, see the CSS SVG stroke buttons collection.