Pure CSSMIT licensed

Dual Layer Stroke Button with Offset Trailing Path

A telemetry panel where the lap button is a skewed blade, not a rectangle, and its outline is drawn twice: a crisp 2px leader and a wide, blurred follower running 90ms behind it. The gap between them opens mid-draw and closes at the end, which the eye reads as speed rather than as two separate lines.

Live Demo
Plain CSSTailwind v4
Try it

Nucleo: 44,000+ SVG icons in five families · All Icons Bundle $149

Nucleo · Affiliate link

Get the Nucleo bundle

The code

<section class="svgb-12">
  <input class="svgb-12__ti" type="checkbox" id="svgb-12-theme">
  <label class="svgb-12__toggle" for="svgb-12-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-12__sr">Switch colour scheme</span>
  </label>
  <div class="svgb-12__stage">
    <div class="svgb-12__panel">
      <div class="svgb-12__telem">
        <div class="svgb-12__t"><span class="svgb-12__tk">Lap</span><span class="svgb-12__tv">14</span></div>
        <div class="svgb-12__t"><span class="svgb-12__tk">Delta</span><span class="svgb-12__tv svgb-12__tv--good">-0.412</span></div>
        <div class="svgb-12__t"><span class="svgb-12__tk">Tyre</span><span class="svgb-12__tv">C3 &middot; 62%</span></div>
        <div class="svgb-12__t"><span class="svgb-12__tk">ERS</span><span class="svgb-12__tv">2.1 MJ</span></div>
      </div>

      <button class="svgb-12__blade" type="button">
        <svg class="svgb-12__frame" viewBox="0 0 340 78" aria-hidden="true">
          <path class="svgb-12__base" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__trail" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__lead" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
        </svg>
        <span class="svgb-12__btext">Push lap</span>
      </button>

      <button class="svgb-12__blade svgb-12__blade--comet" type="button">
        <svg class="svgb-12__frame" viewBox="0 0 340 78" aria-hidden="true">
          <path class="svgb-12__base" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__comet" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__spark" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
        </svg>
        <span class="svgb-12__btext">Deploy overtake</span>
      </button>

      <p class="svgb-12__note">leader 620ms &middot; trail 800ms + 90ms &middot; paint order: trail first</p>
    </div>
  </div>
</section>
@import url('https://fonts.googleapis.com/css2?family=Saira+Condensed:wght@400;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

.svgb-12 {
  --svgb-12-bg: #08090a;
  --svgb-12-bg: oklch(0.145 0.002 250);
  --svgb-12-fg: #edeff1;
  --svgb-12-fg: oklch(0.95 0.003 250);
  --svgb-12-muted: #83878d;
  --svgb-12-muted: oklch(0.645 0.008 250);
  --svgb-12-rest: rgba(237, 239, 241, 0.14);
  --svgb-12-rest: oklch(0.95 0.003 250 / 0.14);
  --svgb-12-stroke: #00e5ff;
  --svgb-12-stroke: oklch(0.85 0.15 205);
  --svgb-12-good: #7cff8f;
  --svgb-12-good: oklch(0.89 0.18 145);
  --svgb-12-blend: screen;
  position: relative;
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  background: var(--svgb-12-bg);
  color: var(--svgb-12-fg);
  font-family: 'Saira Condensed', system-ui, sans-serif;
  overflow: hidden;
}

.svgb-12 *,
.svgb-12 *::before,
.svgb-12 *::after {
  box-sizing: border-box;
}

.svgb-12::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(45deg, oklch(1 0 0 / 0.022) 0 2px, transparent 2px 5px), repeating-linear-gradient(-45deg, oklch(1 0 0 / 0.022) 0 2px, transparent 2px 5px), radial-gradient(70% 60% at 50% 40%, color-mix(in oklab, var(--svgb-12-stroke) 8%, transparent), transparent 70%);
}

.svgb-12__stage {
  position: relative;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: clamp(22px, 5vw, 70px);
}

.svgb-12__panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(16px, 3vw, 26px);
  width: 100%;
  max-width: 420px;
}

.svgb-12__telem {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 20px;
  width: 100%;
}

.svgb-12__t {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-block-end: 8px;
  border-block-end: 1px solid var(--svgb-12-rest);
}

.svgb-12__tk {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--svgb-12-muted);
}

.svgb-12__tv {
  font-size: 26px;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.svgb-12__tv--good {
  color: var(--svgb-12-good);
}

.svgb-12__blade {
  position: relative;
  inline-size: min(340px, 92vw);
  block-size: 78px;
  display: grid;
  place-items: center;
  border: 0;
  padding: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 20px;
  font-weight: 600;
  font-style: italic;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  isolation: isolate;
}

.svgb-12__btext {
  position: relative;
  z-index: 2;
  transition: color 300ms ease, letter-spacing 400ms cubic-bezier(0.22, 1, 0.36, 1);
}

.svgb-12__blade:hover .svgb-12__btext,
.svgb-12__blade:focus-visible .svgb-12__btext {
  color: var(--svgb-12-stroke);
  letter-spacing: 0.16em;
}

.svgb-12__blade:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--svgb-12-stroke) 34%, transparent);
}

.svgb-12__frame {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  overflow: visible;
}

.svgb-12__frame path {
  fill: none;
  stroke-linejoin: miter;
}

.svgb-12__base {
  stroke: var(--svgb-12-rest);
  stroke-width: 1.4px;
}

.svgb-12__trail {
  stroke: var(--svgb-12-stroke);
  stroke-width: 7px;
  opacity: 0.36;
  color: var(--svgb-12-stroke);
  filter: drop-shadow(0 0 10px currentColor);
  mix-blend-mode: var(--svgb-12-blend);
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 800ms cubic-bezier(0.22, 1, 0.36, 1) 90ms;
}

.svgb-12__lead {
  stroke: var(--svgb-12-stroke);
  stroke-width: 2px;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 620ms cubic-bezier(0.22, 1, 0.36, 1);
}

.svgb-12__blade:hover .svgb-12__trail,
.svgb-12__blade:focus-visible .svgb-12__trail,
.svgb-12__blade:hover .svgb-12__lead,
.svgb-12__blade:focus-visible .svgb-12__lead {
  stroke-dashoffset: 0;
}

.svgb-12__comet {
  stroke: var(--svgb-12-stroke);
  stroke-width: 6px;
  opacity: 0.32;
  color: var(--svgb-12-stroke);
  filter: drop-shadow(0 0 12px currentColor);
  mix-blend-mode: var(--svgb-12-blend);
  stroke-dasharray: 0.16 0.84;
  stroke-dashoffset: 0.16;
  transition: stroke-dashoffset 900ms linear;
}

.svgb-12__spark {
  stroke: var(--svgb-12-fg);
  stroke-width: 2.4px;
  stroke-dasharray: 0.045 0.955;
  stroke-dashoffset: 0.045;
  transition: stroke-dashoffset 900ms linear;
}

.svgb-12__blade--comet:hover .svgb-12__comet,
.svgb-12__blade--comet:focus-visible .svgb-12__comet {
  stroke-dashoffset: -0.84;
}

.svgb-12__blade--comet:hover .svgb-12__spark,
.svgb-12__blade--comet:focus-visible .svgb-12__spark {
  stroke-dashoffset: -0.955;
}

.svgb-12__note {
  margin: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--svgb-12-muted);
}

.svgb-12__ti {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.svgb-12__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: 4px;
  border: 1px solid color-mix(in oklab, currentColor 22%, transparent);
  background: color-mix(in oklab, currentColor 8%, transparent);
  color: inherit;
  cursor: pointer;
  transition: background 160ms ease, transform 160ms ease;
}

.svgb-12__toggle:hover {
  background: color-mix(in oklab, currentColor 15%, transparent);
}

.svgb-12__toggle:active {
  transform: scale(0.94);
}

.svgb-12__toggle svg {
  inline-size: 18px;
  block-size: 18px;
  transition: transform 400ms cubic-bezier(0.2, 0.7, 0.3, 1);
}

.svgb-12__ti:checked + .svgb-12__toggle svg {
  transform: rotate(180deg);
}

.svgb-12__ti:focus-visible + .svgb-12__toggle {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.svgb-12__sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.svgb-12:has(#svgb-12-theme:checked) {
  --svgb-12-bg: #f1f2f4;
  --svgb-12-bg: oklch(0.955 0.003 250);
  --svgb-12-fg: #101214;
  --svgb-12-fg: oklch(0.185 0.004 250);
  --svgb-12-muted: #555a60;
  --svgb-12-muted: oklch(0.49 0.008 250);
  --svgb-12-rest: rgba(16, 18, 20, 0.16);
  --svgb-12-rest: oklch(0.185 0.004 250 / 0.16);
  --svgb-12-stroke: #00647f;
  --svgb-12-stroke: oklch(0.45 0.11 215);
  --svgb-12-good: #0d6b2c;
  --svgb-12-good: oklch(0.46 0.14 148);
  --svgb-12-blend: multiply;
}

.svgb-12:has(#svgb-12-theme:checked)::before {
  background: repeating-linear-gradient(45deg, oklch(0 0 0 / 0.03) 0 2px, transparent 2px 5px), repeating-linear-gradient(-45deg, oklch(0 0 0 / 0.03) 0 2px, transparent 2px 5px);
}

@media (prefers-reduced-motion: reduce) {
  .svgb-12__trail,
    .svgb-12__lead,
    .svgb-12__comet,
    .svgb-12__spark,
    .svgb-12__btext {
    transition: none;
    filter: none;
  }

  .svgb-12__trail,
    .svgb-12__comet,
    .svgb-12__spark {
    opacity: 0;
  }

  .svgb-12__lead {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    opacity: 0;
  }

  .svgb-12__blade:hover .svgb-12__lead,
    .svgb-12__blade:focus-visible .svgb-12__lead {
    opacity: 1;
  }

  .svgb-12__toggle,
    .svgb-12__toggle svg {
    transition: none;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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: Dual Layer Stroke Button with Offset Trailing Path
Source: https://codefronts.com/components/css-svg-stroke-buttons/dual-layer-stroke-button-with-offset-trailing-path/

A telemetry panel where the lap button is a skewed blade, not a rectangle, and its outline is drawn twice: a crisp 2px leader and a wide, blurred follower running 90ms behind it. The gap between them opens mid-draw and closes at the end, which the eye reads as speed rather than as two separate lines.
## HTML
```html
<section class="svgb-12">
  <input class="svgb-12__ti" type="checkbox" id="svgb-12-theme">
  <label class="svgb-12__toggle" for="svgb-12-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-12__sr">Switch colour scheme</span>
  </label>
  <div class="svgb-12__stage">
    <div class="svgb-12__panel">
      <div class="svgb-12__telem">
        <div class="svgb-12__t"><span class="svgb-12__tk">Lap</span><span class="svgb-12__tv">14</span></div>
        <div class="svgb-12__t"><span class="svgb-12__tk">Delta</span><span class="svgb-12__tv svgb-12__tv--good">-0.412</span></div>
        <div class="svgb-12__t"><span class="svgb-12__tk">Tyre</span><span class="svgb-12__tv">C3 &middot; 62%</span></div>
        <div class="svgb-12__t"><span class="svgb-12__tk">ERS</span><span class="svgb-12__tv">2.1 MJ</span></div>
      </div>

      <button class="svgb-12__blade" type="button">
        <svg class="svgb-12__frame" viewBox="0 0 340 78" aria-hidden="true">
          <path class="svgb-12__base" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__trail" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__lead" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
        </svg>
        <span class="svgb-12__btext">Push lap</span>
      </button>

      <button class="svgb-12__blade svgb-12__blade--comet" type="button">
        <svg class="svgb-12__frame" viewBox="0 0 340 78" aria-hidden="true">
          <path class="svgb-12__base" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__comet" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
          <path class="svgb-12__spark" d="M26 3H337L314 75H3Z" pathLength="1" vector-effect="non-scaling-stroke"/>
        </svg>
        <span class="svgb-12__btext">Deploy overtake</span>
      </button>

      <p class="svgb-12__note">leader 620ms &middot; trail 800ms + 90ms &middot; paint order: trail first</p>
    </div>
  </div>
</section>
```
## CSS
```css
@import url('https://fonts.googleapis.com/css2?family=Saira+Condensed:wght@400;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

.svgb-12 {
  --svgb-12-bg: #08090a;
  --svgb-12-bg: oklch(0.145 0.002 250);
  --svgb-12-fg: #edeff1;
  --svgb-12-fg: oklch(0.95 0.003 250);
  --svgb-12-muted: #83878d;
  --svgb-12-muted: oklch(0.645 0.008 250);
  --svgb-12-rest: rgba(237, 239, 241, 0.14);
  --svgb-12-rest: oklch(0.95 0.003 250 / 0.14);
  --svgb-12-stroke: #00e5ff;
  --svgb-12-stroke: oklch(0.85 0.15 205);
  --svgb-12-good: #7cff8f;
  --svgb-12-good: oklch(0.89 0.18 145);
  --svgb-12-blend: screen;
  position: relative;
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  background: var(--svgb-12-bg);
  color: var(--svgb-12-fg);
  font-family: 'Saira Condensed', system-ui, sans-serif;
  overflow: hidden;
}

.svgb-12 *,
.svgb-12 *::before,
.svgb-12 *::after {
  box-sizing: border-box;
}

.svgb-12::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(45deg, oklch(1 0 0 / 0.022) 0 2px, transparent 2px 5px), repeating-linear-gradient(-45deg, oklch(1 0 0 / 0.022) 0 2px, transparent 2px 5px), radial-gradient(70% 60% at 50% 40%, color-mix(in oklab, var(--svgb-12-stroke) 8%, transparent), transparent 70%);
}

.svgb-12__stage {
  position: relative;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: clamp(22px, 5vw, 70px);
}

.svgb-12__panel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(16px, 3vw, 26px);
  width: 100%;
  max-width: 420px;
}

.svgb-12__telem {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 20px;
  width: 100%;
}

.svgb-12__t {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-block-end: 8px;
  border-block-end: 1px solid var(--svgb-12-rest);
}

.svgb-12__tk {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--svgb-12-muted);
}

.svgb-12__tv {
  font-size: 26px;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.svgb-12__tv--good {
  color: var(--svgb-12-good);
}

.svgb-12__blade {
  position: relative;
  inline-size: min(340px, 92vw);
  block-size: 78px;
  display: grid;
  place-items: center;
  border: 0;
  padding: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 20px;
  font-weight: 600;
  font-style: italic;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  isolation: isolate;
}

.svgb-12__btext {
  position: relative;
  z-index: 2;
  transition: color 300ms ease, letter-spacing 400ms cubic-bezier(0.22, 1, 0.36, 1);
}

.svgb-12__blade:hover .svgb-12__btext,
.svgb-12__blade:focus-visible .svgb-12__btext {
  color: var(--svgb-12-stroke);
  letter-spacing: 0.16em;
}

.svgb-12__blade:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--svgb-12-stroke) 34%, transparent);
}

.svgb-12__frame {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  overflow: visible;
}

.svgb-12__frame path {
  fill: none;
  stroke-linejoin: miter;
}

.svgb-12__base {
  stroke: var(--svgb-12-rest);
  stroke-width: 1.4px;
}

.svgb-12__trail {
  stroke: var(--svgb-12-stroke);
  stroke-width: 7px;
  opacity: 0.36;
  color: var(--svgb-12-stroke);
  filter: drop-shadow(0 0 10px currentColor);
  mix-blend-mode: var(--svgb-12-blend);
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 800ms cubic-bezier(0.22, 1, 0.36, 1) 90ms;
}

.svgb-12__lead {
  stroke: var(--svgb-12-stroke);
  stroke-width: 2px;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 620ms cubic-bezier(0.22, 1, 0.36, 1);
}

.svgb-12__blade:hover .svgb-12__trail,
.svgb-12__blade:focus-visible .svgb-12__trail,
.svgb-12__blade:hover .svgb-12__lead,
.svgb-12__blade:focus-visible .svgb-12__lead {
  stroke-dashoffset: 0;
}

.svgb-12__comet {
  stroke: var(--svgb-12-stroke);
  stroke-width: 6px;
  opacity: 0.32;
  color: var(--svgb-12-stroke);
  filter: drop-shadow(0 0 12px currentColor);
  mix-blend-mode: var(--svgb-12-blend);
  stroke-dasharray: 0.16 0.84;
  stroke-dashoffset: 0.16;
  transition: stroke-dashoffset 900ms linear;
}

.svgb-12__spark {
  stroke: var(--svgb-12-fg);
  stroke-width: 2.4px;
  stroke-dasharray: 0.045 0.955;
  stroke-dashoffset: 0.045;
  transition: stroke-dashoffset 900ms linear;
}

.svgb-12__blade--comet:hover .svgb-12__comet,
.svgb-12__blade--comet:focus-visible .svgb-12__comet {
  stroke-dashoffset: -0.84;
}

.svgb-12__blade--comet:hover .svgb-12__spark,
.svgb-12__blade--comet:focus-visible .svgb-12__spark {
  stroke-dashoffset: -0.955;
}

.svgb-12__note {
  margin: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--svgb-12-muted);
}

.svgb-12__ti {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.svgb-12__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: 4px;
  border: 1px solid color-mix(in oklab, currentColor 22%, transparent);
  background: color-mix(in oklab, currentColor 8%, transparent);
  color: inherit;
  cursor: pointer;
  transition: background 160ms ease, transform 160ms ease;
}

.svgb-12__toggle:hover {
  background: color-mix(in oklab, currentColor 15%, transparent);
}

.svgb-12__toggle:active {
  transform: scale(0.94);
}

.svgb-12__toggle svg {
  inline-size: 18px;
  block-size: 18px;
  transition: transform 400ms cubic-bezier(0.2, 0.7, 0.3, 1);
}

.svgb-12__ti:checked + .svgb-12__toggle svg {
  transform: rotate(180deg);
}

.svgb-12__ti:focus-visible + .svgb-12__toggle {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.svgb-12__sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.svgb-12:has(#svgb-12-theme:checked) {
  --svgb-12-bg: #f1f2f4;
  --svgb-12-bg: oklch(0.955 0.003 250);
  --svgb-12-fg: #101214;
  --svgb-12-fg: oklch(0.185 0.004 250);
  --svgb-12-muted: #555a60;
  --svgb-12-muted: oklch(0.49 0.008 250);
  --svgb-12-rest: rgba(16, 18, 20, 0.16);
  --svgb-12-rest: oklch(0.185 0.004 250 / 0.16);
  --svgb-12-stroke: #00647f;
  --svgb-12-stroke: oklch(0.45 0.11 215);
  --svgb-12-good: #0d6b2c;
  --svgb-12-good: oklch(0.46 0.14 148);
  --svgb-12-blend: multiply;
}

.svgb-12:has(#svgb-12-theme:checked)::before {
  background: repeating-linear-gradient(45deg, oklch(0 0 0 / 0.03) 0 2px, transparent 2px 5px), repeating-linear-gradient(-45deg, oklch(0 0 0 / 0.03) 0 2px, transparent 2px 5px);
}

@media (prefers-reduced-motion: reduce) {
  .svgb-12__trail,
    .svgb-12__lead,
    .svgb-12__comet,
    .svgb-12__spark,
    .svgb-12__btext {
    transition: none;
    filter: none;
  }

  .svgb-12__trail,
    .svgb-12__comet,
    .svgb-12__spark {
    opacity: 0;
  }

  .svgb-12__lead {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    opacity: 0;
  }

  .svgb-12__blade:hover .svgb-12__lead,
    .svgb-12__blade:focus-visible .svgb-12__lead {
    opacity: 1;
  }

  .svgb-12__toggle,
    .svgb-12__toggle svg {
    transition: none;
  }
}
```

How this works

The lag is the whole effect. Give the follower a slightly longer duration and a small delay and the two heads separate mid-draw, then converge as both land on zero. Because the trail is wider and softer, the eye reads the gap as motion blur rather than as two lines.

.svgb-12__lead {
  stroke-width: 2px;
  transition: stroke-dashoffset 620ms cubic-bezier(.22,1,.36,1);
}
.svgb-12__trail {
  stroke-width: 6px;
  opacity: .45;
  filter: drop-shadow(0 0 8px currentColor);
  transition: stroke-dashoffset 780ms cubic-bezier(.22,1,.36,1) 90ms;
}

Order matters in SVG. There is no z-index for SVG children — paint order is document order. The trail must come first in the markup so the crisp leader paints on top of it; swap them and the soft wide stroke smears over the sharp one.

Blend mode keeps the overlap honest. Where trail and leader coincide, two semi-transparent strokes of the same hue stack into a darker, dirtier line. screen on dark backgrounds makes that overlap brighter instead, which is how light actually behaves; on a light ground the same logic needs multiply.

One extra layer is the limit. Three or four stacked strokes look like a printing misregistration, and each one adds a filter pass. Two layers plus a drop-shadow is the point of diminishing returns.

Make it yours

  • Widen the gap by raising the trail delay to 150ms for a slower, more liquid feel; drop it to 40ms for a tight metallic edge.
  • Remove the drop-shadow and instead give the trail 12px of stroke width at 0.12 opacity for a flat, printed halo.
  • Make the trail a different hue — a warm leader over a cool trail reads as chromatic aberration and suits editorial layouts.
  • Use the comet variant for loading states: a 0.15 dash segment chasing a 0.05 leader around a normalised path.
  • Match the trail's easing to the leader's exactly if the effect looks jittery; different curves make the gap pulse rather than open smoothly.

Gotchas — read before shipping

  • SVG paints in document order and ignores z-index. The soft trail must be written before the crisp leader.
  • filter on an SVG child creates a new rasterised layer on every frame. One filtered path per button is fine; one per card in a grid of forty is not.
  • A drop-shadow inherits the element's own colour only if you pass currentColor — hard-coding the glow hue means it will not follow the theme flip.
  • Stacked semi-transparent strokes of the same colour darken at the overlap unless you set a lightening blend mode, and blend modes need an isolation boundary or they will reach the page background.

Browser support

ChromeSafariFirefoxEdge
111+15.4+113+111+

Stacked paths, transition-delay and filter: drop-shadow() work in all current engines. mix-blend-mode on SVG children is supported in Chromium, Firefox and Safari 15.4+; where it is missing the overlap is slightly darker and nothing breaks.

Techniques used in this demo

Search CodeFronts

Loading…