Components

Marching Border

Animated dashed border overlay that conforms to its parent's corner radius

Preview

Bundle: Reading list

3 unsaved changes. Confirm to publish, or discard to revert.

Installation

Usage

MarchingBorder renders as an absolutely-positioned SVG overlay. Drop it inside any positioned parent (position: relative or another positioned ancestor) with a rounded-* class, and the dashed border conforms to that radius automatically. Because the overlay lives outside the parent's box model, toggling it on or off causes zero layout shift — useful for staged edit states, pending changes, drag-over indicators, and similar pattern-driven UI signals.

Color comes from currentColor — set it via a Tailwind text-* class on the SVG itself.

Examples

Variants

Tune dash, gap, strokeWidth, and duration for different visual moods. dash and gap are expressed as percentages of the path's perimeter, so the pattern tiles consistently across element sizes.

Default
Fine + fast
Chunky + slow

Explicit radius

When the parent doesn't carry a rounded-* class — for example, a <canvas> or a custom-shaped panel — set radius directly. Pass 0 for a perfectly rectangular border.

No rounded-* class
radius=24

API Reference

MarchingBorder is a single SVG component. It accepts any native <svg> prop in addition to those documented below; spread props land on the root <svg> element.

Props

Prop

Notes

  • Parent positioning. The SVG is absolute inset-0, so the parent must be positioned (relative, absolute, fixed, or sticky). Without that, the border attaches to the nearest positioned ancestor instead.
  • Seam-free loop. pathLength is rounded to a whole multiple of dash + gap, so the pattern tiles around the perimeter an exact integer number of times regardless of element size. The path also starts at the midpoint of the top edge so any residual subpixel error sits on a straight side rather than a corner.
  • Shared keyframe. A single @keyframes dash-march rule is shared across every instance via an inline <style>. The end offset is driven by a per-instance CSS variable on the path, so changing dash / gap doesn't generate new keyframes.
  • Reduced motion. Under prefers-reduced-motion: reduce the marching animation is suppressed, but the dashed border itself still renders — for an edit-mode signal, the static dashes are the primary cue and shouldn't disappear entirely.
  • Color. The stroke uses currentColor. Set the color with a Tailwind text-* class (e.g. text-primary, text-destructive) directly on the component.