14 / 20
All 20 in 20 CSS SVG Stroke Buttons
- 01SVG Stroke Draw Button Border on Hover
- 02Stroke Dashoffset Button Outline Animation
- 03Corner Start Perimeter Draw Button
- 04Two Path Split Border Draw Button
- 05Rounded Rect Stroke Button with rx Radius
- 06Dashed Marching Ants Button Border
- 07Gradient Stroke Button with SVG linearGradient
- 08Stroke Draw Button That Reverses on Mouse Leave
- 09Focus Visible Stroke Outline for Keyboard Users
- 10Non Scaling Stroke Button That Resizes with Text
- 11Stroke Draw Button with pathLength Normalization
- 12Dual Layer Stroke Button with Offset Trailing Path
- 13Sequential Stroke and Label Fade Button
- 14Icon Plus Border Stroke Draw Together
- 15Stroke Draw Submit Button Loading State
- 16Stroke Draw Button Disabled and Error States
- 17Scroll Triggered Button Stroke with animation-timeline
- 18Stroke Draw Button Group with Staggered Delay
- 19Reduced Motion Fallback for Stroke Buttons
- 20Variable Width Stroke Button with Text Length
Icon Plus Border Stroke Draw Together
A seven-day forecast strip where each day is a ring and a hand-drawn weather glyph — and both draw at once. The ring is hundreds of units long, the glyphs are a few dozen, so both carry pathLength="1" and one duration keeps them in step. Multi-stroke glyphs are split into separate paths so the shaft can lead the arrowhead by 60ms.
Nucleo: 44,000+ SVG icons in five families · All Icons Bundle $149
Nucleo · Affiliate link
The code
<section class="svgb-14">
<input class="svgb-14__ti" type="checkbox" id="svgb-14-theme">
<label class="svgb-14__toggle" for="svgb-14-theme">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><circle cx="12" cy="12" r="8.5"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor" stroke="none"/></svg>
<span class="svgb-14__sr">Switch colour scheme</span>
</label>
<div class="svgb-14__stage">
<div class="svgb-14__wrap">
<div class="svgb-14__head">
<h1 class="svgb-14__place">Fjord House</h1>
<p class="svgb-14__cond">Light rain easing after noon · 11°</p>
</div>
<div class="svgb-14__strip">
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Mon</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<circle class="svgb-14__gbase" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
<circle class="svgb-14__draw svgb-14__draw--i1" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">14°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Tue</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__gbase" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">11°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Wed</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__gbase" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">9°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Thu</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">4°</span>
</button>
</div>
<div class="svgb-14__legend">
<span class="svgb-14__lg">scalloped ring · 12 lobes</span>
<span class="svgb-14__lg">glyph 40–90 units</span>
<span class="svgb-14__lg">pathLength 1 · one duration</span>
</div>
</div>
</div>
</section><section class="svgb-14">
<input class="svgb-14__ti" type="checkbox" id="svgb-14-theme">
<label class="svgb-14__toggle" for="svgb-14-theme">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><circle cx="12" cy="12" r="8.5"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor" stroke="none"/></svg>
<span class="svgb-14__sr">Switch colour scheme</span>
</label>
<div class="svgb-14__stage">
<div class="svgb-14__wrap">
<div class="svgb-14__head">
<h1 class="svgb-14__place">Fjord House</h1>
<p class="svgb-14__cond">Light rain easing after noon · 11°</p>
</div>
<div class="svgb-14__strip">
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Mon</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<circle class="svgb-14__gbase" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
<circle class="svgb-14__draw svgb-14__draw--i1" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">14°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Tue</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__gbase" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">11°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Wed</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__gbase" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">9°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Thu</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">4°</span>
</button>
</div>
<div class="svgb-14__legend">
<span class="svgb-14__lg">scalloped ring · 12 lobes</span>
<span class="svgb-14__lg">glyph 40–90 units</span>
<span class="svgb-14__lg">pathLength 1 · one duration</span>
</div>
</div>
</div>
</section>@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600&family=JetBrains+Mono:wght@400&display=swap');
.svgb-14 {
--svgb-14-bg: #eef1e9;
--svgb-14-bg: oklch(0.945 0.015 130);
--svgb-14-fg: #1a201a;
--svgb-14-fg: oklch(0.225 0.015 145);
--svgb-14-muted: #6b7568;
--svgb-14-muted: oklch(0.545 0.018 140);
--svgb-14-panel: #f8faf5;
--svgb-14-panel: oklch(0.982 0.008 130);
--svgb-14-rest: rgba(26, 32, 26, 0.14);
--svgb-14-rest: oklch(0.225 0.015 145 / 0.14);
--svgb-14-stroke: #2f6b4f;
--svgb-14-stroke: oklch(0.47 0.10 158);
--svgb-14-dur: 640ms;
--svgb-14-ease: cubic-bezier(0.22, 1, 0.36, 1);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--svgb-14-bg);
position: relative;
color: var(--svgb-14-fg);
font-family: 'Nunito', system-ui, sans-serif;
}
.svgb-14 *,
.svgb-14 *::before,
.svgb-14 *::after {
box-sizing: border-box;
}
.svgb-14__stage {
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(22px, 5vw, 70px);
}
.svgb-14__wrap {
width: 100%;
max-width: 860px;
display: flex;
flex-direction: column;
gap: clamp(20px, 3.5vw, 34px);
}
.svgb-14__head {
display: flex;
flex-direction: column;
gap: 6px;
}
.svgb-14__place {
margin: 0;
font-size: clamp(28px, 4.6vw, 46px);
font-weight: 600;
letter-spacing: -0.03em;
}
.svgb-14__cond {
margin: 0;
font-size: 15px;
color: var(--svgb-14-muted);
}
.svgb-14__strip {
display: grid;
gap: clamp(12px, 2vw, 20px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
}
.svgb-14__day {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
padding: clamp(18px, 3vw, 26px) 12px;
border: 0;
border-radius: 22px;
background: var(--svgb-14-panel);
color: inherit;
font: inherit;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
box-shadow: 0 1px 2px oklch(0 0 0 / 0.04);
transition: transform 320ms var(--svgb-14-ease), box-shadow 320ms ease;
}
.svgb-14__day:hover {
transform: translateY(-3px);
box-shadow: 0 10px 26px -18px oklch(0 0 0 / 0.4);
}
.svgb-14__day:focus-visible {
outline: 2px solid var(--svgb-14-stroke);
outline-offset: 3px;
}
.svgb-14__dl {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--svgb-14-muted);
}
.svgb-14__pod {
position: relative;
inline-size: 88px;
block-size: 88px;
display: grid;
place-items: center;
}
.svgb-14__ring {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
overflow: visible;
}
.svgb-14__ring path,
.svgb-14__icon path,
.svgb-14__icon circle {
fill: none;
}
.svgb-14__ring path {
stroke-linejoin: round;
}
.svgb-14__base {
stroke: var(--svgb-14-rest);
stroke-width: 1.4px;
}
.svgb-14__gbase {
stroke: var(--svgb-14-rest);
stroke-width: 1.6px;
stroke-linecap: round;
stroke-linejoin: round;
}
.svgb-14__icon {
position: relative;
inline-size: 40px;
block-size: 40px;
overflow: visible;
color: var(--svgb-14-stroke);
}
.svgb-14__temp {
font-size: 21px;
font-weight: 600;
letter-spacing: -0.02em;
font-variant-numeric: tabular-nums;
transition: color 300ms ease;
}
.svgb-14__day:hover .svgb-14__temp,
.svgb-14__day:focus-visible .svgb-14__temp {
color: var(--svgb-14-stroke);
}
.svgb-14__draw {
stroke: var(--svgb-14-stroke);
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 1;
stroke-dashoffset: 1;
transition: stroke-dashoffset var(--svgb-14-dur) var(--svgb-14-ease);
}
.svgb-14__icon .svgb-14__draw {
stroke-width: 1.8px;
}
.svgb-14__draw--i2 {
transition-delay: 60ms;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
stroke-dashoffset: 0;
}
.svgb-14__legend {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.svgb-14__lg {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 10.5px;
color: var(--svgb-14-muted);
}
.svgb-14__ti {
position: absolute;
opacity: 0;
pointer-events: none;
}
.svgb-14__toggle {
position: absolute;
z-index: 5;
inset-block-start: 16px;
inset-inline-end: 16px;
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border-radius: 999px;
border: 1px solid color-mix(in oklab, currentColor 20%, transparent);
background: color-mix(in oklab, currentColor 7%, transparent);
color: inherit;
cursor: pointer;
transition: background 160ms ease, transform 160ms ease;
}
.svgb-14__toggle:hover {
background: color-mix(in oklab, currentColor 14%, transparent);
}
.svgb-14__toggle:active {
transform: scale(0.94);
}
.svgb-14__toggle svg {
inline-size: 18px;
block-size: 18px;
transition: transform 400ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.svgb-14__ti:checked + .svgb-14__toggle svg {
transform: rotate(180deg);
}
.svgb-14__ti:focus-visible + .svgb-14__toggle {
outline: 2px solid currentColor;
outline-offset: 3px;
}
.svgb-14__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.svgb-14:has(#svgb-14-theme:checked) {
--svgb-14-bg: #101410;
--svgb-14-bg: oklch(0.185 0.012 145);
--svgb-14-fg: #eaf0e8;
--svgb-14-fg: oklch(0.945 0.012 140);
--svgb-14-muted: #8b978a;
--svgb-14-muted: oklch(0.665 0.018 140);
--svgb-14-panel: #171d17;
--svgb-14-panel: oklch(0.235 0.014 145);
--svgb-14-rest: rgba(234, 240, 232, 0.16);
--svgb-14-rest: oklch(0.945 0.012 140 / 0.16);
--svgb-14-stroke: #86e0ac;
--svgb-14-stroke: oklch(0.86 0.13 155);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.05);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day:hover {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.08), 0 14px 30px -22px #000;
}
@media (prefers-reduced-motion: reduce) {
.svgb-14__draw {
transition: none !important;
transition-delay: 0ms !important;
stroke-dasharray: none;
stroke-dashoffset: 0;
opacity: 0;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
opacity: 1;
}
.svgb-14__day,
.svgb-14__temp,
.svgb-14__toggle,
.svgb-14__toggle svg {
transition: none;
}
.svgb-14__day:hover {
transform: none;
}
}@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600&family=JetBrains+Mono:wght@400&display=swap');
.svgb-14 {
--svgb-14-bg: #eef1e9;
--svgb-14-bg: oklch(0.945 0.015 130);
--svgb-14-fg: #1a201a;
--svgb-14-fg: oklch(0.225 0.015 145);
--svgb-14-muted: #6b7568;
--svgb-14-muted: oklch(0.545 0.018 140);
--svgb-14-panel: #f8faf5;
--svgb-14-panel: oklch(0.982 0.008 130);
--svgb-14-rest: rgba(26, 32, 26, 0.14);
--svgb-14-rest: oklch(0.225 0.015 145 / 0.14);
--svgb-14-stroke: #2f6b4f;
--svgb-14-stroke: oklch(0.47 0.10 158);
--svgb-14-dur: 640ms;
--svgb-14-ease: cubic-bezier(0.22, 1, 0.36, 1);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--svgb-14-bg);
position: relative;
color: var(--svgb-14-fg);
font-family: 'Nunito', system-ui, sans-serif;
}
.svgb-14 *,
.svgb-14 *::before,
.svgb-14 *::after {
box-sizing: border-box;
}
.svgb-14__stage {
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(22px, 5vw, 70px);
}
.svgb-14__wrap {
width: 100%;
max-width: 860px;
display: flex;
flex-direction: column;
gap: clamp(20px, 3.5vw, 34px);
}
.svgb-14__head {
display: flex;
flex-direction: column;
gap: 6px;
}
.svgb-14__place {
margin: 0;
font-size: clamp(28px, 4.6vw, 46px);
font-weight: 600;
letter-spacing: -0.03em;
}
.svgb-14__cond {
margin: 0;
font-size: 15px;
color: var(--svgb-14-muted);
}
.svgb-14__strip {
display: grid;
gap: clamp(12px, 2vw, 20px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
}
.svgb-14__day {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
padding: clamp(18px, 3vw, 26px) 12px;
border: 0;
border-radius: 22px;
background: var(--svgb-14-panel);
color: inherit;
font: inherit;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
box-shadow: 0 1px 2px oklch(0 0 0 / 0.04);
transition: transform 320ms var(--svgb-14-ease), box-shadow 320ms ease;
}
.svgb-14__day:hover {
transform: translateY(-3px);
box-shadow: 0 10px 26px -18px oklch(0 0 0 / 0.4);
}
.svgb-14__day:focus-visible {
outline: 2px solid var(--svgb-14-stroke);
outline-offset: 3px;
}
.svgb-14__dl {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--svgb-14-muted);
}
.svgb-14__pod {
position: relative;
inline-size: 88px;
block-size: 88px;
display: grid;
place-items: center;
}
.svgb-14__ring {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
overflow: visible;
}
.svgb-14__ring path,
.svgb-14__icon path,
.svgb-14__icon circle {
fill: none;
}
.svgb-14__ring path {
stroke-linejoin: round;
}
.svgb-14__base {
stroke: var(--svgb-14-rest);
stroke-width: 1.4px;
}
.svgb-14__gbase {
stroke: var(--svgb-14-rest);
stroke-width: 1.6px;
stroke-linecap: round;
stroke-linejoin: round;
}
.svgb-14__icon {
position: relative;
inline-size: 40px;
block-size: 40px;
overflow: visible;
color: var(--svgb-14-stroke);
}
.svgb-14__temp {
font-size: 21px;
font-weight: 600;
letter-spacing: -0.02em;
font-variant-numeric: tabular-nums;
transition: color 300ms ease;
}
.svgb-14__day:hover .svgb-14__temp,
.svgb-14__day:focus-visible .svgb-14__temp {
color: var(--svgb-14-stroke);
}
.svgb-14__draw {
stroke: var(--svgb-14-stroke);
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 1;
stroke-dashoffset: 1;
transition: stroke-dashoffset var(--svgb-14-dur) var(--svgb-14-ease);
}
.svgb-14__icon .svgb-14__draw {
stroke-width: 1.8px;
}
.svgb-14__draw--i2 {
transition-delay: 60ms;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
stroke-dashoffset: 0;
}
.svgb-14__legend {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.svgb-14__lg {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 10.5px;
color: var(--svgb-14-muted);
}
.svgb-14__ti {
position: absolute;
opacity: 0;
pointer-events: none;
}
.svgb-14__toggle {
position: absolute;
z-index: 5;
inset-block-start: 16px;
inset-inline-end: 16px;
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border-radius: 999px;
border: 1px solid color-mix(in oklab, currentColor 20%, transparent);
background: color-mix(in oklab, currentColor 7%, transparent);
color: inherit;
cursor: pointer;
transition: background 160ms ease, transform 160ms ease;
}
.svgb-14__toggle:hover {
background: color-mix(in oklab, currentColor 14%, transparent);
}
.svgb-14__toggle:active {
transform: scale(0.94);
}
.svgb-14__toggle svg {
inline-size: 18px;
block-size: 18px;
transition: transform 400ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.svgb-14__ti:checked + .svgb-14__toggle svg {
transform: rotate(180deg);
}
.svgb-14__ti:focus-visible + .svgb-14__toggle {
outline: 2px solid currentColor;
outline-offset: 3px;
}
.svgb-14__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.svgb-14:has(#svgb-14-theme:checked) {
--svgb-14-bg: #101410;
--svgb-14-bg: oklch(0.185 0.012 145);
--svgb-14-fg: #eaf0e8;
--svgb-14-fg: oklch(0.945 0.012 140);
--svgb-14-muted: #8b978a;
--svgb-14-muted: oklch(0.665 0.018 140);
--svgb-14-panel: #171d17;
--svgb-14-panel: oklch(0.235 0.014 145);
--svgb-14-rest: rgba(234, 240, 232, 0.16);
--svgb-14-rest: oklch(0.945 0.012 140 / 0.16);
--svgb-14-stroke: #86e0ac;
--svgb-14-stroke: oklch(0.86 0.13 155);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.05);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day:hover {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.08), 0 14px 30px -22px #000;
}
@media (prefers-reduced-motion: reduce) {
.svgb-14__draw {
transition: none !important;
transition-delay: 0ms !important;
stroke-dasharray: none;
stroke-dashoffset: 0;
opacity: 0;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
opacity: 1;
}
.svgb-14__day,
.svgb-14__temp,
.svgb-14__toggle,
.svgb-14__toggle svg {
transition: none;
}
.svgb-14__day:hover {
transform: none;
}
}Here's a working CSS SVG Stroke Button from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Icon Plus Border Stroke Draw Together
Source: https://codefronts.com/components/css-svg-stroke-buttons/icon-plus-border-stroke-draw-together/
A seven-day forecast strip where each day is a ring and a hand-drawn weather glyph — and both draw at once. The ring is hundreds of units long, the glyphs are a few dozen, so both carry pathLength="1" and one duration keeps them in step. Multi-stroke glyphs are split into separate paths so the shaft can lead the arrowhead by 60ms.
## HTML
```html
<section class="svgb-14">
<input class="svgb-14__ti" type="checkbox" id="svgb-14-theme">
<label class="svgb-14__toggle" for="svgb-14-theme">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><circle cx="12" cy="12" r="8.5"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor" stroke="none"/></svg>
<span class="svgb-14__sr">Switch colour scheme</span>
</label>
<div class="svgb-14__stage">
<div class="svgb-14__wrap">
<div class="svgb-14__head">
<h1 class="svgb-14__place">Fjord House</h1>
<p class="svgb-14__cond">Light rain easing after noon · 11°</p>
</div>
<div class="svgb-14__strip">
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Mon</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<circle class="svgb-14__gbase" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
<circle class="svgb-14__draw svgb-14__draw--i1" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">14°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Tue</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__gbase" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">11°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Wed</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__gbase" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">9°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Thu</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">4°</span>
</button>
</div>
<div class="svgb-14__legend">
<span class="svgb-14__lg">scalloped ring · 12 lobes</span>
<span class="svgb-14__lg">glyph 40–90 units</span>
<span class="svgb-14__lg">pathLength 1 · one duration</span>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600&family=JetBrains+Mono:wght@400&display=swap');
.svgb-14 {
--svgb-14-bg: #eef1e9;
--svgb-14-bg: oklch(0.945 0.015 130);
--svgb-14-fg: #1a201a;
--svgb-14-fg: oklch(0.225 0.015 145);
--svgb-14-muted: #6b7568;
--svgb-14-muted: oklch(0.545 0.018 140);
--svgb-14-panel: #f8faf5;
--svgb-14-panel: oklch(0.982 0.008 130);
--svgb-14-rest: rgba(26, 32, 26, 0.14);
--svgb-14-rest: oklch(0.225 0.015 145 / 0.14);
--svgb-14-stroke: #2f6b4f;
--svgb-14-stroke: oklch(0.47 0.10 158);
--svgb-14-dur: 640ms;
--svgb-14-ease: cubic-bezier(0.22, 1, 0.36, 1);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--svgb-14-bg);
position: relative;
color: var(--svgb-14-fg);
font-family: 'Nunito', system-ui, sans-serif;
}
.svgb-14 *,
.svgb-14 *::before,
.svgb-14 *::after {
box-sizing: border-box;
}
.svgb-14__stage {
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(22px, 5vw, 70px);
}
.svgb-14__wrap {
width: 100%;
max-width: 860px;
display: flex;
flex-direction: column;
gap: clamp(20px, 3.5vw, 34px);
}
.svgb-14__head {
display: flex;
flex-direction: column;
gap: 6px;
}
.svgb-14__place {
margin: 0;
font-size: clamp(28px, 4.6vw, 46px);
font-weight: 600;
letter-spacing: -0.03em;
}
.svgb-14__cond {
margin: 0;
font-size: 15px;
color: var(--svgb-14-muted);
}
.svgb-14__strip {
display: grid;
gap: clamp(12px, 2vw, 20px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
}
.svgb-14__day {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
padding: clamp(18px, 3vw, 26px) 12px;
border: 0;
border-radius: 22px;
background: var(--svgb-14-panel);
color: inherit;
font: inherit;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
box-shadow: 0 1px 2px oklch(0 0 0 / 0.04);
transition: transform 320ms var(--svgb-14-ease), box-shadow 320ms ease;
}
.svgb-14__day:hover {
transform: translateY(-3px);
box-shadow: 0 10px 26px -18px oklch(0 0 0 / 0.4);
}
.svgb-14__day:focus-visible {
outline: 2px solid var(--svgb-14-stroke);
outline-offset: 3px;
}
.svgb-14__dl {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--svgb-14-muted);
}
.svgb-14__pod {
position: relative;
inline-size: 88px;
block-size: 88px;
display: grid;
place-items: center;
}
.svgb-14__ring {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
overflow: visible;
}
.svgb-14__ring path,
.svgb-14__icon path,
.svgb-14__icon circle {
fill: none;
}
.svgb-14__ring path {
stroke-linejoin: round;
}
.svgb-14__base {
stroke: var(--svgb-14-rest);
stroke-width: 1.4px;
}
.svgb-14__gbase {
stroke: var(--svgb-14-rest);
stroke-width: 1.6px;
stroke-linecap: round;
stroke-linejoin: round;
}
.svgb-14__icon {
position: relative;
inline-size: 40px;
block-size: 40px;
overflow: visible;
color: var(--svgb-14-stroke);
}
.svgb-14__temp {
font-size: 21px;
font-weight: 600;
letter-spacing: -0.02em;
font-variant-numeric: tabular-nums;
transition: color 300ms ease;
}
.svgb-14__day:hover .svgb-14__temp,
.svgb-14__day:focus-visible .svgb-14__temp {
color: var(--svgb-14-stroke);
}
.svgb-14__draw {
stroke: var(--svgb-14-stroke);
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 1;
stroke-dashoffset: 1;
transition: stroke-dashoffset var(--svgb-14-dur) var(--svgb-14-ease);
}
.svgb-14__icon .svgb-14__draw {
stroke-width: 1.8px;
}
.svgb-14__draw--i2 {
transition-delay: 60ms;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
stroke-dashoffset: 0;
}
.svgb-14__legend {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.svgb-14__lg {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 10.5px;
color: var(--svgb-14-muted);
}
.svgb-14__ti {
position: absolute;
opacity: 0;
pointer-events: none;
}
.svgb-14__toggle {
position: absolute;
z-index: 5;
inset-block-start: 16px;
inset-inline-end: 16px;
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border-radius: 999px;
border: 1px solid color-mix(in oklab, currentColor 20%, transparent);
background: color-mix(in oklab, currentColor 7%, transparent);
color: inherit;
cursor: pointer;
transition: background 160ms ease, transform 160ms ease;
}
.svgb-14__toggle:hover {
background: color-mix(in oklab, currentColor 14%, transparent);
}
.svgb-14__toggle:active {
transform: scale(0.94);
}
.svgb-14__toggle svg {
inline-size: 18px;
block-size: 18px;
transition: transform 400ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.svgb-14__ti:checked + .svgb-14__toggle svg {
transform: rotate(180deg);
}
.svgb-14__ti:focus-visible + .svgb-14__toggle {
outline: 2px solid currentColor;
outline-offset: 3px;
}
.svgb-14__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.svgb-14:has(#svgb-14-theme:checked) {
--svgb-14-bg: #101410;
--svgb-14-bg: oklch(0.185 0.012 145);
--svgb-14-fg: #eaf0e8;
--svgb-14-fg: oklch(0.945 0.012 140);
--svgb-14-muted: #8b978a;
--svgb-14-muted: oklch(0.665 0.018 140);
--svgb-14-panel: #171d17;
--svgb-14-panel: oklch(0.235 0.014 145);
--svgb-14-rest: rgba(234, 240, 232, 0.16);
--svgb-14-rest: oklch(0.945 0.012 140 / 0.16);
--svgb-14-stroke: #86e0ac;
--svgb-14-stroke: oklch(0.86 0.13 155);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.05);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day:hover {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.08), 0 14px 30px -22px #000;
}
@media (prefers-reduced-motion: reduce) {
.svgb-14__draw {
transition: none !important;
transition-delay: 0ms !important;
stroke-dasharray: none;
stroke-dashoffset: 0;
opacity: 0;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
opacity: 1;
}
.svgb-14__day,
.svgb-14__temp,
.svgb-14__toggle,
.svgb-14__toggle svg {
transition: none;
}
.svgb-14__day:hover {
transform: none;
}
}
```Here's a working CSS SVG Stroke Button from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Icon Plus Border Stroke Draw Together
Source: https://codefronts.com/components/css-svg-stroke-buttons/icon-plus-border-stroke-draw-together/
A seven-day forecast strip where each day is a ring and a hand-drawn weather glyph — and both draw at once. The ring is hundreds of units long, the glyphs are a few dozen, so both carry pathLength="1" and one duration keeps them in step. Multi-stroke glyphs are split into separate paths so the shaft can lead the arrowhead by 60ms.
## HTML
```html
<section class="svgb-14">
<input class="svgb-14__ti" type="checkbox" id="svgb-14-theme">
<label class="svgb-14__toggle" for="svgb-14-theme">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><circle cx="12" cy="12" r="8.5"/><path d="M12 3.5a8.5 8.5 0 0 0 0 17Z" fill="currentColor" stroke="none"/></svg>
<span class="svgb-14__sr">Switch colour scheme</span>
</label>
<div class="svgb-14__stage">
<div class="svgb-14__wrap">
<div class="svgb-14__head">
<h1 class="svgb-14__place">Fjord House</h1>
<p class="svgb-14__cond">Light rain easing after noon · 11°</p>
</div>
<div class="svgb-14__strip">
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Mon</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<circle class="svgb-14__gbase" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
<circle class="svgb-14__draw svgb-14__draw--i1" cx="16" cy="16" r="7" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 3v3m0 20v3M3 16h3m20 0h3M6.8 6.8l2.1 2.1m14.3 14.3 2.1 2.1M25.2 6.8l-2.1 2.1M8.9 23.1l-2.1 2.1" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">14°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Tue</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__gbase" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M9 19a5.5 5.5 0 0 1 .8-11A7 7 0 0 1 23 10.5a4.3 4.3 0 0 1 0 8.5Z" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M12 23l-1.5 4M18 23l-1.5 4M24 23l-1.5 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">11°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Wed</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__gbase" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M3 12h15a4 4 0 1 0-4-4" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M3 20h20a4 4 0 1 1-4 4" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">9°</span>
</button>
<button class="svgb-14__day" type="button">
<span class="svgb-14__dl">Thu</span>
<span class="svgb-14__pod">
<svg class="svgb-14__ring" viewBox="0 0 88 88" aria-hidden="true">
<path class="svgb-14__base" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
<path class="svgb-14__draw" d="M44.00 6.00A19 19 0 0 1 63.00 11.09A19 19 0 0 1 76.91 25.00A19 19 0 0 1 82.00 44.00A19 19 0 0 1 76.91 63.00A19 19 0 0 1 63.00 76.91A19 19 0 0 1 44.00 82.00A19 19 0 0 1 25.00 76.91A19 19 0 0 1 11.09 63.00A19 19 0 0 1 6.00 44.00A19 19 0 0 1 11.09 25.00A19 19 0 0 1 25.00 11.09A19 19 0 0 1 44.00 6.00Z" pathLength="1"/>
</svg>
<svg class="svgb-14__icon" viewBox="0 0 32 32" aria-hidden="true">
<path class="svgb-14__gbase" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__gbase" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i1" d="M16 5v22M6.5 10.5l19 11M25.5 10.5l-19 11" pathLength="1"/>
<path class="svgb-14__draw svgb-14__draw--i2" d="M16 5l-3 3m3-3 3 3m-3 22-3-3m3 3 3-3" pathLength="1"/>
</svg>
</span>
<span class="svgb-14__temp">4°</span>
</button>
</div>
<div class="svgb-14__legend">
<span class="svgb-14__lg">scalloped ring · 12 lobes</span>
<span class="svgb-14__lg">glyph 40–90 units</span>
<span class="svgb-14__lg">pathLength 1 · one duration</span>
</div>
</div>
</div>
</section>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600&family=JetBrains+Mono:wght@400&display=swap');
.svgb-14 {
--svgb-14-bg: #eef1e9;
--svgb-14-bg: oklch(0.945 0.015 130);
--svgb-14-fg: #1a201a;
--svgb-14-fg: oklch(0.225 0.015 145);
--svgb-14-muted: #6b7568;
--svgb-14-muted: oklch(0.545 0.018 140);
--svgb-14-panel: #f8faf5;
--svgb-14-panel: oklch(0.982 0.008 130);
--svgb-14-rest: rgba(26, 32, 26, 0.14);
--svgb-14-rest: oklch(0.225 0.015 145 / 0.14);
--svgb-14-stroke: #2f6b4f;
--svgb-14-stroke: oklch(0.47 0.10 158);
--svgb-14-dur: 640ms;
--svgb-14-ease: cubic-bezier(0.22, 1, 0.36, 1);
width: 100%;
min-height: 100vh;
min-height: 100svh;
display: block;
background: var(--svgb-14-bg);
position: relative;
color: var(--svgb-14-fg);
font-family: 'Nunito', system-ui, sans-serif;
}
.svgb-14 *,
.svgb-14 *::before,
.svgb-14 *::after {
box-sizing: border-box;
}
.svgb-14__stage {
min-height: 100svh;
display: grid;
place-items: center;
padding: clamp(22px, 5vw, 70px);
}
.svgb-14__wrap {
width: 100%;
max-width: 860px;
display: flex;
flex-direction: column;
gap: clamp(20px, 3.5vw, 34px);
}
.svgb-14__head {
display: flex;
flex-direction: column;
gap: 6px;
}
.svgb-14__place {
margin: 0;
font-size: clamp(28px, 4.6vw, 46px);
font-weight: 600;
letter-spacing: -0.03em;
}
.svgb-14__cond {
margin: 0;
font-size: 15px;
color: var(--svgb-14-muted);
}
.svgb-14__strip {
display: grid;
gap: clamp(12px, 2vw, 20px);
grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
}
.svgb-14__day {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
padding: clamp(18px, 3vw, 26px) 12px;
border: 0;
border-radius: 22px;
background: var(--svgb-14-panel);
color: inherit;
font: inherit;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
box-shadow: 0 1px 2px oklch(0 0 0 / 0.04);
transition: transform 320ms var(--svgb-14-ease), box-shadow 320ms ease;
}
.svgb-14__day:hover {
transform: translateY(-3px);
box-shadow: 0 10px 26px -18px oklch(0 0 0 / 0.4);
}
.svgb-14__day:focus-visible {
outline: 2px solid var(--svgb-14-stroke);
outline-offset: 3px;
}
.svgb-14__dl {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 11px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--svgb-14-muted);
}
.svgb-14__pod {
position: relative;
inline-size: 88px;
block-size: 88px;
display: grid;
place-items: center;
}
.svgb-14__ring {
position: absolute;
inset: 0;
inline-size: 100%;
block-size: 100%;
overflow: visible;
}
.svgb-14__ring path,
.svgb-14__icon path,
.svgb-14__icon circle {
fill: none;
}
.svgb-14__ring path {
stroke-linejoin: round;
}
.svgb-14__base {
stroke: var(--svgb-14-rest);
stroke-width: 1.4px;
}
.svgb-14__gbase {
stroke: var(--svgb-14-rest);
stroke-width: 1.6px;
stroke-linecap: round;
stroke-linejoin: round;
}
.svgb-14__icon {
position: relative;
inline-size: 40px;
block-size: 40px;
overflow: visible;
color: var(--svgb-14-stroke);
}
.svgb-14__temp {
font-size: 21px;
font-weight: 600;
letter-spacing: -0.02em;
font-variant-numeric: tabular-nums;
transition: color 300ms ease;
}
.svgb-14__day:hover .svgb-14__temp,
.svgb-14__day:focus-visible .svgb-14__temp {
color: var(--svgb-14-stroke);
}
.svgb-14__draw {
stroke: var(--svgb-14-stroke);
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 1;
stroke-dashoffset: 1;
transition: stroke-dashoffset var(--svgb-14-dur) var(--svgb-14-ease);
}
.svgb-14__icon .svgb-14__draw {
stroke-width: 1.8px;
}
.svgb-14__draw--i2 {
transition-delay: 60ms;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
stroke-dashoffset: 0;
}
.svgb-14__legend {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.svgb-14__lg {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 10.5px;
color: var(--svgb-14-muted);
}
.svgb-14__ti {
position: absolute;
opacity: 0;
pointer-events: none;
}
.svgb-14__toggle {
position: absolute;
z-index: 5;
inset-block-start: 16px;
inset-inline-end: 16px;
display: grid;
place-items: center;
inline-size: 44px;
block-size: 44px;
border-radius: 999px;
border: 1px solid color-mix(in oklab, currentColor 20%, transparent);
background: color-mix(in oklab, currentColor 7%, transparent);
color: inherit;
cursor: pointer;
transition: background 160ms ease, transform 160ms ease;
}
.svgb-14__toggle:hover {
background: color-mix(in oklab, currentColor 14%, transparent);
}
.svgb-14__toggle:active {
transform: scale(0.94);
}
.svgb-14__toggle svg {
inline-size: 18px;
block-size: 18px;
transition: transform 400ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.svgb-14__ti:checked + .svgb-14__toggle svg {
transform: rotate(180deg);
}
.svgb-14__ti:focus-visible + .svgb-14__toggle {
outline: 2px solid currentColor;
outline-offset: 3px;
}
.svgb-14__sr {
position: absolute;
inline-size: 1px;
block-size: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
.svgb-14:has(#svgb-14-theme:checked) {
--svgb-14-bg: #101410;
--svgb-14-bg: oklch(0.185 0.012 145);
--svgb-14-fg: #eaf0e8;
--svgb-14-fg: oklch(0.945 0.012 140);
--svgb-14-muted: #8b978a;
--svgb-14-muted: oklch(0.665 0.018 140);
--svgb-14-panel: #171d17;
--svgb-14-panel: oklch(0.235 0.014 145);
--svgb-14-rest: rgba(234, 240, 232, 0.16);
--svgb-14-rest: oklch(0.945 0.012 140 / 0.16);
--svgb-14-stroke: #86e0ac;
--svgb-14-stroke: oklch(0.86 0.13 155);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.05);
}
.svgb-14:has(#svgb-14-theme:checked) .svgb-14__day:hover {
box-shadow: inset 0 0 0 1px oklch(1 0 0 / 0.08), 0 14px 30px -22px #000;
}
@media (prefers-reduced-motion: reduce) {
.svgb-14__draw {
transition: none !important;
transition-delay: 0ms !important;
stroke-dasharray: none;
stroke-dashoffset: 0;
opacity: 0;
}
.svgb-14__day:hover .svgb-14__draw,
.svgb-14__day:focus-visible .svgb-14__draw {
opacity: 1;
}
.svgb-14__day,
.svgb-14__temp,
.svgb-14__toggle,
.svgb-14__toggle svg {
transition: none;
}
.svgb-14__day:hover {
transform: none;
}
}
```How this works
Different lengths, same clock. A button frame is hundreds of units long; a chevron is a few dozen. Animate both with a raw dash constant and the icon finishes almost instantly while the frame is a third of the way round. pathLength="1" on both makes progress proportional, so a shared 620ms duration puts both heads at the same fraction of their own path at every instant.
<!-- frame and glyph, same normalised length -->
<rect pathLength="1" .../>
<path pathLength="1" d="M4 12h15"/>
<path pathLength="1" d="M13.5 6.5 19 12l-5.5 5.5"/>
.svgb-14__draw {
stroke-dasharray: 1; stroke-dashoffset: 1;
transition: stroke-dashoffset 620ms cubic-bezier(.22,1,.36,1);
}Every subpath restarts the dash. A dash pattern begins again at each M command, so a two-stroke icon written as one d attribute reveals both halves simultaneously. Splitting the glyph into separate elements gives you control: a 60ms stagger between the shaft and the arrowhead is what makes an arrow look drawn rather than switched on.
Sync order changes the meaning. Frame-then-icon reads as a container being prepared and then filled — good for a menu or a panel trigger. Icon-then-frame reads as the action asserting itself and the button forming around it — good for a primary CTA. Fully simultaneous is the most neutral and the safest default.
Only stroked icons can do this. A filled icon has no path to reveal; you would be animating a fill, which needs a clip or a mask instead. If your icon set ships as filled shapes, this technique needs an outline variant — most modern icon libraries provide one.
Make it yours
- Set the icon stagger to 0 for a machine-precise feel, or 80–120ms for something hand-drawn.
- Give the icon a slightly thinner stroke than the frame (1.7px against 2px) so the glyph reads as finer detail rather than a second border.
- Add a small
rotateortranslateon the icon group timed to land as the last subpath completes — the drawing then hands off into a movement. - Swap the arrow for a download, plus or play glyph; the CSS is untouched as long as the new paths carry
pathLength. - Reverse the icon draw with a negative resting offset so the chevron appears to be drawn from its tip backwards.
Gotchas — read before shipping
- Without
pathLengththe icon finishes long before the frame, which looks like two unrelated animations. Normalise both. - A dash pattern restarts at every subpath, so one
dwith severalMcommands cannot be staggered. Split it into elements. - Filled icons cannot be stroke-drawn at all. Use an outline icon set, or animate a mask.
- Round caps on very short subpaths can leave a visible dot at zero progress. Give short strokes butt caps, or start them at a tiny non-zero offset.
- Icons that carry meaning need
aria-hiddenplus real text, or a<title>. An icon that draws itself is still invisible to a screen reader.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 113+ | 111+ |
pathLength on path and basic shapes plus dash transitions: supported in all current engines (Firefox gained pathLength on basic shapes in 92). oklch() and :has() set the stated floor.