Line drawing

Draw icons, paths, or explanatory connectors with stroke offset animation.

Preview

Live preview

An SVG path that draws itself in, like an invisible pen tracing it.

Preview
Authoritative vocabulary

Definition and close-term distinctions

English definitions are preserved verbatim from Animation Vocabulary; translations and distinctions help you choose precisely.

Canonical termline-drawing

Line drawing

线条绘制
Authoritative definition

An SVG path that draws itself in, like an invisible pen tracing it.

Chinese translation

SVG 路径像被一支隐形画笔描摹一样自行绘制出来。

Browse all 91 terms
Design contract

Decide before this motion ships

Purpose, frequency, trigger, timing, interruptibility, and gesture rules shape the implementation.

Purpose

Draw an SVG path progressively to emphasize how an icon, flow, or explanatory connection forms.

Frequency

Reserve for low-frequency brand moments and explanations, showing frequent icons immediately.

Trigger

Trigger on first presentation or explicit replay, ordering paths by visual reading direction.

Enter / exit

Draw from full dash offset to zero on enter and usually fade the complete line on exit.

Interruptibility

Reset clearly before replay and preserve the currently visible path if interrupted.

Gesture and keyboard

No gesture is required; replay supports keyboard input and the graphic has a textual meaning.

Reduced-motion strategy

Show the complete path immediately or with one very short fade.

Output

Copy into your interface

Current parameters update visual-state CSS, semantic HTML, the required vanilla JS runtime, and an interaction prompt.

Updates with parameters
motion.css
.motion-demo.motion-demo--line-drawing {
  position: relative;
  display: grid;
  place-items: center;
  width: min(100%, 34rem);
  min-height: 15rem;
  padding: 2rem;
  overflow: hidden;
  color: #18181b;
  background: #fafafa;
  border: 1px solid #e4e4e7;
  border-radius: 12px;
  isolation: isolate;
}

.motion-demo.motion-demo--line-drawing *, .motion-demo.motion-demo--line-drawing *::before, .motion-demo.motion-demo--line-drawing *::after {
  box-sizing: border-box;
}

.motion-demo.motion-demo--line-drawing .motion-surface {
  position: relative;
  display: grid;
  gap: 0.65rem;
  width: min(100%, 18rem);
  padding: 1.25rem;
  background: #ffffff;
  border: 1px solid #e4e4e7;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 6%), 0 10px 28px rgb(0 0 0 / 7%);
}

.motion-demo.motion-demo--line-drawing .motion-line {
  display: block;
  width: 100%;
  height: 0.5rem;
  background: #e4e4e7;
  border-radius: 999px;
}

.motion-demo.motion-demo--line-drawing .motion-line:last-child { width: 62%; }

.motion-demo.motion-demo--line-drawing .motion-button {
  position: relative;
  min-height: 2.75rem;
  padding: 0.75rem 1.1rem;
  color: white;
  font: inherit;
  font-weight: 700;
  background: #18181b;
  border: 0;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--line-drawing .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }

.motion-demo.motion-demo--line-drawing .motion-action-row {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  margin-top: 0.85rem;
}

.motion-demo.motion-demo--line-drawing .motion-replay-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--line-drawing .motion-pausable-scene {
  width: min(100%, 22rem);
  display: grid;
  place-items: center;
}

.motion-demo.motion-demo--line-drawing button.motion-surface {
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.motion-demo.motion-demo--line-drawing .motion-replay-button,
.motion-demo.motion-demo--line-drawing .motion-undo-button,
.motion-demo.motion-demo--line-drawing .motion-dismiss-button,
.motion-demo.motion-demo--line-drawing .motion-pause-button {
  min-height: 2.75rem;
  padding: 0.65rem 0.9rem;
  color: #18181b;
  font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
  background: #ffffff;
  border: 1px solid #d4d4d8;
  border-radius: 7px;
  cursor: pointer;
}

.motion-demo.motion-demo--line-drawing .motion-replay-button:focus-visible,
.motion-demo.motion-demo--line-drawing .motion-undo-button:focus-visible,
.motion-demo.motion-demo--line-drawing .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--line-drawing .motion-pause-button:focus-visible,
.motion-demo.motion-demo--line-drawing [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--line-drawing [data-swipe-target]:focus-visible {
  outline: 3px solid rgb(37 99 235 / 32%);
  outline-offset: 3px;
}

.motion-demo.motion-demo--line-drawing .motion-status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.motion-demo.motion-demo--line-drawing .motion-ripple-ink {
  position: absolute;
  width: 12px;
  height: 12px;
  pointer-events: none;
  background: rgb(255 255 255 / 72%);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0.95);
  opacity: 0;
}

.motion-demo.motion-demo--line-drawing .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--line-drawing .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 8px; }
.motion-demo.motion-demo--line-drawing .motion-state--to { background: #18181b; color: white; }

.motion-demo.motion-demo--line-drawing .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--line-drawing .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--line-drawing .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--line-drawing svg { width: min(100%, 20rem); height: auto; }

.motion-demo.motion-demo--line-drawing .motion-path { fill: none; stroke: #2563eb; stroke-width: 5; stroke-linecap: round; stroke-dasharray: 260; stroke-dashoffset: 260; animation: motion-line-drawing 1000ms cubic-bezier(0.33, 1, 0.68, 1) 0ms both; }
@keyframes motion-line-drawing { to { stroke-dashoffset: 0; } }

@keyframes motion-line-drawing-reduced-fade {
  from { opacity: 0.84; }
  to { opacity: 1; }
}

.force-reduced-motion .motion-demo.motion-demo--line-drawing {
  animation: motion-line-drawing-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}

.force-reduced-motion .motion-demo.motion-demo--line-drawing *,
.force-reduced-motion .motion-demo.motion-demo--line-drawing *::before,
.force-reduced-motion .motion-demo.motion-demo--line-drawing *::after {
  animation: none !important;
  animation-delay: 0ms !important;
  animation-iteration-count: 1 !important;
  transition-property: opacity, color, background-color, border-color !important;
  transition-duration: 160ms !important;
  transition-delay: 0ms !important;
  scroll-behavior: auto !important;
}

.force-reduced-motion .motion-demo.motion-demo--line-drawing .motion-button,
.force-reduced-motion .motion-demo.motion-demo--line-drawing [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--line-drawing [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--line-drawing [data-spring-target] {
  transform: none !important;
}

.force-reduced-motion .motion-demo.motion-demo--line-drawing .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--line-drawing .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--line-drawing .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
  .motion-demo.motion-demo--line-drawing {
    animation: motion-line-drawing-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
  }

  .motion-demo.motion-demo--line-drawing *, .motion-demo.motion-demo--line-drawing *::before, .motion-demo.motion-demo--line-drawing *::after {
    animation: none !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity, color, background-color, border-color !important;
    transition-duration: 160ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .motion-demo.motion-demo--line-drawing .motion-button,
  .motion-demo.motion-demo--line-drawing [data-reorder-item],
  .motion-demo.motion-demo--line-drawing [data-swipe-target],
  .motion-demo.motion-demo--line-drawing [data-spring-target] {
    transform: none !important;
  }

  .motion-demo.motion-demo--line-drawing .motion-path { stroke-dashoffset: 0 !important; }
  .motion-demo.motion-demo--line-drawing .motion-word--from { opacity: 0 !important; visibility: hidden; }
  .motion-demo.motion-demo--line-drawing .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}
Review notes

Pre-delivery review

  • Normalize pathLength and dasharray across SVG assets.
  • Align drawing order with the information logic.
Accessibility

Keep information accessible

Reduced motion

Show the complete path immediately or with one very short fade.

Parameters

Parameter reference

ParameterRange / optionsDefaultPurpose
duration500ms–3000ms1000msUses a longer demo duration so the full change stays observable; immediate production UI feedback should stay under 300ms.
delay0ms–600ms0msControls the wait before motion begins.
easeSoft / Snap / Calm / LinearCalmControls how velocity changes over time.