Card lift & border
Card whose SVG border draws itself around it on hover
Techniques: pathLength · stroke-dashoffset · transition-on-hover · preserveAspectRatio-none
<!--
============================================================
SVGarden — https://www.svgarden.dev
Author : Simon-Pierre Boucher
Contact: contact@spboucher.ai
File : snippets/hover/card-lift-border.html
Desc : Card whose SVG border draws itself around it on hover
============================================================
-->
<div class="sg-card-lift-border" tabindex="0" style="--sg-color:#7F77DD; --sg-size:220px; --sg-duration:0.7s;">
<svg viewBox="0 0 200 100" preserveAspectRatio="none" aria-hidden="true" focusable="false">
<rect x="1" y="1" width="198" height="98" rx="8" pathLength="100" />
</svg>
<strong>Hover me</strong>
<span>The border draws itself around the card, then un-draws on leave.</span>
</div>
<style>
.sg-card-lift-border {
position: relative;
width: var(--sg-size);
padding: 1.1rem 1.2rem;
border-radius: 10px;
background: rgba(127, 119, 221, 0.08);
font-family: inherit;
display: flex;
flex-direction: column;
gap: 0.4rem;
cursor: pointer;
transition: transform var(--sg-duration) ease;
}
.sg-card-lift-border strong { font-size: 1rem; }
.sg-card-lift-border span { font-size: 0.85rem; opacity: 0.75; }
.sg-card-lift-border svg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.sg-card-lift-border rect {
/* no non-scaling-stroke: Chromium computes dash patterns in screen space
with it, which breaks the pathLength=100 normalization */
fill: none;
stroke: var(--sg-color);
stroke-width: 2;
stroke-linecap: round;
stroke-dasharray: 100 102;
stroke-dashoffset: 101;
transition: stroke-dashoffset var(--sg-duration) ease-in-out;
}
.sg-card-lift-border:hover,
.sg-card-lift-border:focus-visible {
transform: translateY(-4px);
}
.sg-card-lift-border:hover rect,
.sg-card-lift-border:focus-visible rect {
stroke-dashoffset: 0;
}
</style>