6 Pure CSS1 with JSPublished 2026-10-05Free · no sign-up
Seven buttons whose outlines and icons are SVG strokes animated with CSS: a border that draws itself on hover, a dash that chases round the edge, corner brackets that close into a frame, an arrow and a tick that draw in, a gradient outline with glow and a link with a hand-drawn underline.
An SVG rectangle sits over the button and its stroke is hidden with stroke-dasharray and stroke-dashoffset. On hover or keyboard focus the offset animates to zero, so the outline draws around the button in one continuous line. pathLength="100" keeps the dash maths simple at any size.
A short bright dash travels round the border on a loop, made by a dash pattern of 18 visible units and 82 gaps whose offset is animated. It suits one important call to action. The animation stops for visitors who prefer reduced motion, leaving a static highlight.
At rest only the four corners of the frame show, like camera brackets. The stroke-dasharray is a list of nine values worked out from the real side lengths so each dash sits on a corner. On hover every dash grows and every gap shrinks to zero, closing the frame evenly from all four corners.
A solid button whose arrow icon is redrawn line by line when the pointer arrives: the shaft first, then the head after a short delay. The label is the accessible name and the icon is aria-hidden, so screen readers hear only Continue.
Clicking toggles aria-pressed, and the pressed state swaps the label to Saved while a tick is drawn inside a filled circle. The state lives on the button itself, so assistive technology announces it as a toggle button that is pressed or not pressed.
The outline is an SVG stroke painted with a linearGradient, which a CSS border cannot do on a rounded shape without extra layers. A drop-shadow filter adds a soft glow that brightens on hover, and the label stays plain white for contrast.
A text link whose underline is a hand-drawn wave in an inline SVG, drawn from left to right on hover and focus with stroke-dashoffset. Because it is a real link it keeps link semantics, and the wave stretches with the text because preserveAspectRatio is none.
View code
<a class="ssb7" href="#pricing">See pricing<svg viewBox="0 0 120 10" preserveAspectRatio="none" aria-hidden="true"><path d="M1 5 Q 8 0 15 5 T 29 5 T 43 5 T 57 5 T 71 5 T 85 5 T 99 5 T 113 5 T 119 5" pathLength="1"/></svg></a>
Every SVG stroke can be broken into dashes with stroke-dasharray and shifted along its path with stroke-dashoffset. Set both to the length of the path and the line disappears; animate the offset back to zero and it draws itself in.
Let pathLength do the maths
Measuring a path's real length means JavaScript or guesswork. Add pathLength="100" (or 1) to the shape and the browser treats the path as that long, so the same dash values work whatever the button's size.
Keep the button a button
The SVG is decoration, so it gets aria-hidden="true" and pointer-events: none, and the visible label stays the accessible name. Hover effects are mirrored on :focus-visible so keyboard users see the same feedback.
Respect reduced motion
Looping stroke animations can distract. Each demo turns its animation off inside prefers-reduced-motion: reduce, leaving a static outline that still shows where the button is.
Frequently asked questions
Do SVG stroke buttons need JavaScript?
No. Only the save toggle uses a line of script to flip aria-pressed; the drawing effects are pure CSS.
Why does the border look thicker at the edges?
A stroke is centred on the shape's edge, so half of it falls outside. overflow: visible on the svg stops it being clipped.
Will these work in every browser?
Yes. Dash animations and pathLength work in all current browsers, including Safari.