SPB Git

spb/svgarden Public

SVGarden — searchable bank of 74 self-contained SVG+CSS animation snippets (svgarden.dev)

HTML 79.2% Astro 10.3% JavaScript 6% CSS 3.7% Shell 0.8%

fix(snippets): card-lift-border dash bleed — drop non-scaling-stroke, oversize dash gap

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed 4 h ago (Aug 10, 2026) parent d14ea90

Showing 1 changed file with +14 and −11

modified snippets/hover/card-lift-border.html +14 −11
@@ -15,12 +15,13 @@ tags: [hover, card, border, draw]
15 15 difficulty: intermediate
16 16 techniques: [pathLength, stroke-dashoffset, transition-on-hover, preserveAspectRatio-none]
17 17 how_it_works: >
18 An SVG rect stretched over the card (preserveAspectRatio="none" + non-scaling
19 stroke) starts fully hidden by its own dash gap. Hovering transitions
20 stroke-dashoffset to zero, so the border traces itself around the perimeter —
21 a transition, not a keyframe animation, which means it elegantly reverses
22 when the pointer leaves instead of snapping. The card lift is a separate
23 translateY transition on the wrapper.
18 + An SVG rect stretched over the card (preserveAspectRatio="none", with a
19 + viewBox matched to the card's aspect ratio so the stroke stays visually even)
20 + starts fully hidden because its dash gap (102) is longer than the normalized
21 + path (pathLength 100) — the extra 2 units keep the round line caps off-path
22 + at rest. Hovering transitions stroke-dashoffset to zero, so the border traces
23 + itself around the perimeter — a transition, not a keyframe animation, which
24 + means it elegantly reverses when the pointer leaves instead of snapping.
24 25 customizable:
25 26 - { var: "--sg-color", label: "Border", type: color, default: "#7F77DD" }
26 27 - { var: "--sg-size", label: "Width", type: range, min: 140, max: 360, default: 220, unit: px }
@@ -28,8 +29,8 @@ customizable:
28 29 created: 2026-08-10
29 30 -->
30 31 <div class="sg-card-lift-border" tabindex="0" style="--sg-color:#7F77DD; --sg-size:220px; --sg-duration:0.7s;">
31 <svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true" focusable="false">
32 <rect x="1" y="1" width="98" height="98" rx="6" pathLength="100" />
32 + <svg viewBox="0 0 200 100" preserveAspectRatio="none" aria-hidden="true" focusable="false">
33 + <rect x="1" y="1" width="198" height="98" rx="8" pathLength="100" />
33 34 </svg>
34 35 <strong>Hover me</strong>
35 36 <span>The border draws itself around the card, then un-draws on leave.</span>
@@ -58,12 +59,14 @@ created: 2026-08-10
58 59 pointer-events: none;
59 60 }
60 61 .sg-card-lift-border rect {
62 + /* no non-scaling-stroke: Chromium computes dash patterns in screen space
63 + with it, which breaks the pathLength=100 normalization */
61 64 fill: none;
62 65 stroke: var(--sg-color);
63 66 stroke-width: 2;
64 vector-effect: non-scaling-stroke;
65 stroke-dasharray: 100;
66 stroke-dashoffset: 100;
67 + stroke-linecap: round;
68 + stroke-dasharray: 100 102;
69 + stroke-dashoffset: 101;
67 70 transition: stroke-dashoffset var(--sg-duration) ease-in-out;
68 71 }
69 72 .sg-card-lift-border:hover,
70 73