Skip to content

[BUG] Zooming in / out in Safari shortens pathLength, breaking SVG stroke animations #3301

@ZkHaider

Description

@ZkHaider

1. Describe the bug
When the user changes the page zoom level in Safari (⌘+ / ⌘− or track-pad pinch), any motion.path that animates the custom pathLength property immediately changes stroke length.
The drawn portion becomes progressively shorter the further you zoom out, resulting in visible clipping of the path animation.
Chrome, Edge and Firefox behave correctly.

2. Reproduction

git clone https://github.com/motiondivision/motion.git
cd motion
make bootstrap      # installs and builds everything
yarn dev            # alias for `yarn run dev`

Then open http://localhost:9991/?example=SVG-path in Safari, and follow the zoom steps in section 3.

3. Steps to reproduce

  1. Open http://localhost:9991/?example=SVG-path in Safari.
  2. Make sure page zoom is 100 %. Click the checkbox once to play the stroke animation – it completes as expected (full rounded rectangle + tick).
  3. Zoom out to 90 %, click again. The stroke covers only ~75 % of the intended length.
  4. Zoom out further to 80 % / 70 % and repeat – the stroke shrinks even more.
  5. Reset zoom; the stroke animates correctly again.

4. Expected behavior
pathLength, stroke-dasharray and stroke-dashoffset should remain logically identical regardless of browser zoom level.

The full path should draw from 0 → 100 % every time, matching non-Safari browsers.

5. Actual behavior
Safari scales the numeric value returned by stroke-dasharray / stroke-dashoffset when zooming, so the dash pattern is no longer normalized to 1.
Because Motion converts pathLength"Xpx Ypx" (absolute pixel units), the values shrink in CSS pixels during zoom, causing the visible shortening.

6. Screenshots

Zoom Screenshot
100 % Image
90 % Image
80 % Image
70 % Image

8. Possible fix
Avoid emitting absolute px units for stroke-dasharray and stroke-dashoffset; instead write unit-less numbers.
Safari does not scale unit-less dash values on zoom, restoring parity with other browsers.

A small patch that resolves the issue locally:

// src/render/svg/utils/path.ts
- attrs[keys.offset] = px.transform!(-offset)
- attrs[keys.array]  = `${px.transform!(length)} ${px.transform!(spacing)}`
+ attrs[keys.offset] = `${typeof offset === "string" ? -parseFloat(offset) : -offset}`
+ attrs[keys.array]  = `${length} ${spacing}`

Note: This keeps the public API unchanged (pathLength, pathSpacing, etc. still accept numbers) and only affects the internal serialization step for SVG paths.

9. Additional context
Similar Safari quirk: WebKit Bug 129248 (“zoom does not scale dash patterns”) – fixed by using unit-less dash values.
Related Framer Motion code: buildSVGPath & svgEffect (pathLengthstroke-dasharray/offset).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions