Skip to main content
Question

Animated SVG exports add additional transform/translate attributes and break the layout

  • July 11, 2026
  • 1 reply
  • 5 views

Marceli Wac

I love the new addition of Figma Motion and it’s exactly what I’ve been looking for. In particular, the ability to export an animated SVG is fantastic and saves me so much time authoring animations “by hand”!

Problem

I do however have a problem with the exported files. When I set up my animation in Figma, everything looks great. Exporting it as SVG adds additional transform attribute to the group, which (if it has animations) completely displaces it by said transform. When I remove the transform attribute from the group, the layout is fixed and resembles what I can see in Figma.

I suppose the source of the problem is somewhere in the code that parses the animation set up in Figma and converts it to the SVG animation keyframes. As the keyframes already specify the position / translation, the additional transform on the group moves the entire group an breaks the offsets specified by the keyframes.

Example

My example uses two rectangles with rounded corners, both of which are within a mask group (alpha) that provides the shared gradient fill. The entire thing is overlayed on top of device frame mockup.

Original animation (viewed in Figma)
 

 

Exported SVG animation (viewed in Chrome)

 

Exported SVG animation after removing the (transform=”translate(17 78.9965)” property (viewed in Chrome)
Screenshot of the relevant SVG code

<svg xmlns="http://www.w3.org/2000/svg" width="640" height="480" viewBox="0 0 640 480" fill="none">
<style>
@keyframes kf_Button_transform_0 {
  0% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  1.67% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  3.33% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  5% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  6.67% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  8.33% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  10% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  11.67% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  13.33% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  15% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  16.67% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  18.33% {
    transform: translateX(17px) translateY(259.009px) translateX(0px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  20% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  21.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  23.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  25% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  26.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  28.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  30% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  31.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  33.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  35% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  36.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  38.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  40% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  41.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  43.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  45% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  46.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  48.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  50% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  51.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  53.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  55% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  56.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  58.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.001px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  60% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  61.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  63.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  65% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  66.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  68.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  70% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  71.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  73.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  75% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  75.27% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0) scaleY(0) translate(-84px, -13.075px);
  }
  76.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1.07) scaleY(1.07) translate(-84px, -13.075px);
  }
  78.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(0.995) scaleY(0.995) translate(-84px, -13.075px);
  }
  79.57% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  80% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  81.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  83.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  85% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  86.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  88.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  90% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  90.32% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(0px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  91.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(-72.346px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  93.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(-161.304px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  95% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(-250.798px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  95.7% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(-288.311px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  96.67% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(-288.311px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  98.33% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(-288.311px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
  100% {
    transform: translateX(17px) translateY(259.009px) translateX(-0.002px) translateY(-288.311px) translate(84px, 13.075px) scaleX(1) scaleY(1) translate(-84px, -13.075px);
  }
}
@keyframes kf_Button_opacity_0 {
  0% {
    animation-timing-function: linear;
    opacity: 1;
  }
  90.32% {
    animation-timing-function: cubic-bezier(0.5, 0, 0.5, 1);
    opacity: 1;
  }
  94.62% {
    animation-timing-function: linear;
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}
#Button {
  transform-origin: 0 0;
  animation:
    kf_Button_transform_0 9.3s linear infinite,
    kf_Button_opacity_0 9.3s linear infinite;
}
@keyframes kf_One_tile_offset_distance_0 {
  0% {
    offset-distance: 0%;
  }
  5.376% {
    offset-distance: 0%;
  }
  6.25% {
    offset-distance: 7.353%;
  }
  7.5% {
    offset-distance: 17.647%;
  }
  8.75% {
    offset-distance: 27.942%;
  }
  9.677% {
    offset-distance: 35.295%;
  }
  27.957% {
    offset-distance: 35.295%;
  }
  28.75% {
    offset-distance: 36.292%;
  }
  30% {
    offset-distance: 37.842%;
  }
  30.108% {
    offset-distance: 37.953%;
  }
  31.25% {
    offset-distance: 41.246%;
  }
  32.5% {
    offset-distance: 45.089%;
  }
  33.75% {
    offset-distance: 48.931%;
  }
  34.409% {
    offset-distance: 51.126%;
  }
  35% {
    offset-distance: 51.801%;
  }
  36.25% {
    offset-distance: 55.006%;
  }
  36.559% {
    offset-distance: 55.175%;
  }
  45.161% {
    offset-distance: 55.175%;
  }
  46.25% {
    offset-distance: 56.14%;
  }
  47.5% {
    offset-distance: 58.392%;
  }
  48.387% {
    offset-distance: 59.035%;
  }
  58.602% {
    offset-distance: 59.035%;
  }
  58.75% {
    offset-distance: 59.196%;
  }
  60% {
    offset-distance: 60.644%;
  }
  61.25% {
    offset-distance: 62.252%;
  }
  61.828% {
    offset-distance: 62.896%;
  }
  89.247% {
    offset-distance: 62.896%;
  }
  90% {
    offset-distance: 67.534%;
  }
  91.25% {
    offset-distance: 76.81%;
  }
  92.5% {
    offset-distance: 86.086%;
  }
  93.75% {
    offset-distance: 93.816%;
  }
  94.624% {
    offset-distance: 100%;
  }
  100% {
    offset-distance: 100%;
  }
}
@keyframes kf_One_tile_opacity_0 {
  0% {
    animation-timing-function: linear;
    opacity: 0;
  }
  5.38% {
    animation-timing-function: cubic-bezier(0.5, 0, 0.5, 1);
    opacity: 0;
  }
  9.68% {
    animation-timing-function: linear;
    opacity: 1;
  }
  89.25% {
    animation-timing-function: cubic-bezier(0.5, 0, 0.5, 1);
    opacity: 1;
  }
  93.55% {
    animation-timing-function: linear;
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}
#One_tile {
  translate: 17px 78.996px;
  transform-origin: 0 0;
  transform-box: view-box;
  offset-path: path('M0 274.255 C0 182.838 0 91.421 0 0.004 C0 0.002 0 0.001 0 0 C2 6.587 4 13.175 6 19.762 C6 53.882 6 88.002 6 122.121 C4 132.415 2 142.709 0 153.003 C0 143.005 0 133.007 0 123.009 C0 113.009 0 103.009 0 93.009 C0 -3.094 0 -99.198 0 -195.302');
  offset-rotate: 0deg;
  offset-anchor: 0px 0px;
  animation:
    kf_One_tile_offset_distance_0 9.3s linear infinite,
    kf_One_tile_opacity_0 9.3s linear infinite;
}
</style>
<g id="app_configure" clip-path="url(#clip0_23_3091)">
<g id="Device_mockup_3" transform="translate(219 29)">
<rect id="Contents_fill" width="202" height="422" rx="25" fill="white"/>
<g id="Device_contents">
<mask id="mask0_23_3091" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="640" height="480">
<g id="Device_contents_2">
<rect id="Button" transform="translate(17 259.009)" width="168" height="26.1499" rx="8" fill="white"/>
<rect id="One_tile" transform="" width="168" height="75" rx="8" fill="white"/>
</g>
</mask>
<g mask="url(#mask0_23_3091)">
<rect id="Contents_fill_2" width="202" height="422" rx="25" fill="url(#paint0_linear_23_3091)"/>
</g>
</g>
<g id="Device_mockup">
<g id="device_frame">
<rect id="iphone_frame" x="3.5" y="3.5" width="195" height="415" rx="21.5" stroke="black" stroke-width="7"/>
<rect id="camera_cutout" transform="matrix(1 0 0 -1 73 31)" width="56" height="17" rx="8.5" fill="black"/>
<rect id="home_button" opacity="0.2" transform="matrix(1 0 0 -1 66 409)" width="70" height="3" rx="1.5" fill="black"/>
</g>
</g>
</g>
</g>
<defs>
<linearGradient id="paint0_linear_23_3091" x1="101" y1="0" x2="101" y2="422" gradientUnits="userSpaceOnUse">
<stop stop-opacity="0.4"/>
<stop offset="1" stop-opacity="0"/>
</linearGradient>
<clipPath id="clip0_23_3091">
<rect width="640" height="480" fill="white"/>
</clipPath>
</defs>
</svg>

 

1 reply

adamsmasher
Figmate
  • Figmate
  • July 12, 2026

Hi, ​@Marceli Wac! Thanks for your post - this is pretty detailed and I appreciate you providing this much information.

 

Does this happen with all animation types you export to an SVG? Meaning, if you set up a simple position animation on a layer in a basic frame, does that also add this additional transform? I’m wondering if we can narrow down if this is something always added, or if there’s some more specific to your example that causes it. In the meantime, I’ve also shared your post with with the team for review.