3D✨ Premium

Path Drawing

A purple curve draws itself from left to right under a dot that travels it, then erases as the dot comes back, 3 s each way: the line is born exactly under the dot, at every moment — pure CSS (stroke-dashoffset + offset-path) kept in step by pathLength="1", full line and still when the user reduces motion.

CSSSVGDraw

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. 3D has 50 effects, including 8 free. Explore the category →

3 usage examples

The homing pigeon's flight from the release point — website of a pigeon racing club — Path Drawing example 1

① The homing pigeon's flight from the release point — website of a pigeon racing club

WhenThe club posts the race result "Release: Orléans — Arrival: Rouen", winner in 3 h 12 min over 118 km; on a simplified map (Loire, Seine, Chartres), the flight line draws itself behind the pigeon, from Orléans to Rouen.
WhyThe line born under the dot tells a flight in progress, not a route already known: you follow the pigeon.
SettingsScene flipped and enlarged with transform: scale(-1.4, 1.4) so the route runs from southeast to northwest; slate line #475569 at 2.4 px; 12 px gray dot with a white ring; towns and rivers placed outside the scene, in page coordinates.
The mountain bike ride's track drawing itself — "Rides" page of a mountain bike club — Path Drawing example 2

② The mountain bike ride's track drawing itself — "Rides" page of a mountain bike club

WhenThe "Rides" page replays Sunday's ride: over a contour-line background, the orange track draws itself from start to finish behind an orange dot (the group), with "34 km" and "780 m climb" in a callout.
WhyRevealing the track step by step lets you follow the ride like a replay; a static track reads like a map, not like a ride.
SettingsOrange line #ea580c at 3 px; 13 px dot with a white ring; contour lines, elevations and start and finish markers in SVG in the scene's coordinate system, scaled by 1.45.
How to write a cursive "l" — handwriting app for 1st graders — Path Drawing example 3

③ How to write a cursive "l" — handwriting app for 1st graders

WhenOn a page of lined French school paper, the letter "l" writes itself: the dot (the pencil) starts on the line, loops up, comes back down and trails off to the right, and the blue line appears behind it. Next to it: "Your turn: follow the model".
WhyShowing the line born under the tip is exactly how you demonstrate a handwriting gesture: the order and direction of the stroke matter as much as the shape.
SettingsDifferent path, the "l", written identically in the d attribute and in offset-path; pathLength="1" does not need to change. Blue line #1d4ed8 at 4.5 px; dark dot with a yellow ring; scene scaled by 1.15.

How it works

The .fx-0039-root block is at least 300 px high, background #0a0a0f, and centers .mp-drawing-scene (300 × 220 px). The scene holds an <svg> of the same size (viewBox="0 0 300 220", 1 unit = 1 px) with a single path, M30,180 Q80,30 150,110 Q220,190 270,60: two arcs that rise, dip and rise again, in purple #8b5cf6, 2 px, round caps. It is 358 px long. On top, a 10 px purple dot with a glow, in position: absolute in the top left corner.

The line is drawn with the dash technique: stroke-dasharray: 1 cuts the line into one full dash and one gap of the same length, and stroke-dashoffset slides that pattern along. At 1, only the gap shows; at 0, the dash covers the whole line. The pathLength="1" attribute on the <path> sets the path's length to 1, whatever its real size: so the dash matches the line exactly, with no math and no JavaScript, and a stroke-dashoffset of 0.4 means "60% drawn".

The dot follows the same path, copied into offset-path: path(…), with offset-distance going from 0 to 100%. Both animations, mpDraw for the line and mpOrbit for the dot, share the same duration (3 s), the same easing (ease-in-out) and the same round trip (alternate): on every frame, the drawn share equals the traveled share. Measured in Chromium, Firefox and WebKit: the line's tip and the dot move by the same percentage (less than 0.1% apart), and the dot's center stays on the line (less than 0.1 px). On the way back, the line erases behind the returning dot. Under prefers-reduced-motion: reduce, a block scoped to .fx-0039-root shows the whole line and sets the dot at the finish.

Accessibility

  • Reduced motion: under prefers-reduced-motion: reduce, the curve is complete and the dot sits at the end, as at the finish of a drawing. Measured in Chromium, Firefox and WebKit: 0 running animations, 0% of pixels change in 800 ms.
  • Route information: if the line stands for a trip or a route, give its start, finish and figures as text (like "Orléans → Rouen, 3 h 12 min" in the first example) and put aria-hidden="true" on the root: a screen reader does not read a drawing.
  • Contrast: the 2 px purple line on #0a0a0f shows well; on a light background or a map, thicken it (3 to 5 px) and pick a strong color, in CSS (stroke, stroke-width).
  • No interaction: the effect reacts to neither mouse, finger nor keyboard.

Browser compatibility

Pure CSS: animated stroke-dasharray and stroke-dashoffset, SVG pathLength attribute, offset-path: path(). No dependency, no JavaScript. Measured in Chromium 151, Firefox 153 and WebKit 26.5: line and dot in step (less than 0.1% apart), dot centered on the line, stop under reduced motion, two independent copies on the page.

Chrome 55+✓ Full
Firefox 72+✓ Full
Safari 16+✓ Full (measured on WebKit 26.5)
Edge 79+✓ Full
Mobile iOS 16+✓ Full
Android Chrome✓ Full

Without offset-path (Safari before 16), the curve draws and erases normally, but the dot stays still in the scene's top left corner (measured by removing the property); @supports not (offset-path: path("M 0 0")) lets you hide it and keep only the line.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0039-root">
  <div class="mp-drawing-scene">                   <!-- 300 × 220 px -->
    <svg viewBox="0 0 300 220" fill="none">
      <path class="mp-drawing-path" pathLength="1"
            d="M30,180 Q80,30 150,110 Q220,190 270,60" …></path>
    </svg>
    <div class="mp-drawing-dot"></div>     <!-- same path in offset-path -->
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Path (HTML + CSS — d attribute and offset-path) M30,180 Q80,30 150,110 Q220,190 270,60 Write the same path in both places, in the coordinates of the 300 × 220 px scene. Thanks to pathLength="1", the line stays in step with the dot with nothing to recompute, whatever the new path's length.
Duration (CSS — 3s in both animations) 3 s each way Change it on the line AND the dot, or they drift apart. Same rule for the easing (ease-in-out).
Draw without erasing (CSS — alternate in both animations) round trip Without alternate, the line draws and then vanishes at once at the start of each cycle. To keep it drawn, use animation-iteration-count: 1 and animation-fill-mode: forwards on both.
Line color and width (CSS — .mp-drawing-path { stroke: …; stroke-width: … }) purple #8b5cf6, 2 px The CSS rule wins over the SVG attributes. Do not add your own stroke-dasharray: that is what draws the line.
Enlarge or flip (CSS — transform on .mp-drawing-scene) none scale(1.5) enlarges line and path together; scale(-1, 1) makes the path start from the right. Do not change only the width: offset-path is in pixels.
Dot (CSS — .mp-drawing-dot) 10 px purple with a glow The dot turns along the curve (offset-rotate: auto): a pencil or bird icon will follow the bends; offset-rotate: 0deg keeps it upright.

FAQ

To draw a line with a dash, you need a dash as long as the line. With the real length (358 px here), you would have to measure it, copy it into the CSS, and redo it all whenever the path changes; a dash that is too long makes the line run ahead of the dot. pathLength="1" tells the browser to count the line as 1: stroke-dasharray: 1 covers it exactly, and the line advances by the same percentage as offset-distance, for any path.
SVG Path Follow shows a curve that is already there, dashed, with a dot shuttling along it and two echoes: a back-and-forth on a known route. Path Drawing makes the line appear under the dot and then erases it: a route in the making (a flight, a GPS track, a handwriting gesture).
Not in this code, which loops as soon as it shows. Set animation-play-state: paused on the line and the dot, then, with an IntersectionObserver, switch them to running when the block enters the screen; add animation-iteration-count: 1 and animation-fill-mode: forwards so the line stays drawn.