Zach’s ugly mug (his face)

Zach Leatherman

Fire SVG animations (SMIL) when the SVG is visible

August 04, 2021 #6 Popular

Had a use case come in where the design had an SVG animation that ran one interation and only one. It looked like this (some content has been removed):

If you’re on a device with a small vertical viewport size, you may not have noticed the above animation. Unfortunately the animations start (and complete!) whether or not the SVG is visible!

I wanted to wire the animations up to IntersectionObserver to make sure they only started animating when visible. Here’s how I did it:

Modify the SVG

I found all of the instances of <animate> or <animateTransform> and wired up the begin attributes to properly cascade the order of the animation internally. I want all of them to start when my bezier curve starts animating, so I added an id to that animation (there was an issue with dashes in that id, so beware using dashes):

<animate
id="mysvgline"
attributeType="xml"
attributeName="stroke-dashoffset"
from="500"
to="0"
dur=".8s"
begin="0s"
/>

Learn how to animate a line/curve: css’s AvatarCSS Tricks: How SVG Line Animation Works

Take note of the begin attribute above, that will be important later.

Now I want to find the other animations in my SVG that I want to start at the same time and change their begin attribute to use the id from above with a .begin suffix. This starts this animation when the referenced animation starts. It looks like this:

<animateMotion
begin="mysvgline.begin"
dur=".8s"
repeatCount="1"
fill="freeze"
path="M35.5 20C216.281 20 352.411 182 512.5 182"
/>

Alternatively, you can use .end to start this animation when the referenced animation ends.

(Side note: repeatCount="1" and fill="freeze" are best buddies. fill="freeze" means that your animation won’t rewind to the first frame at the end)

Next go back to the original animation and change the begin attribute to indefinite (Read more at MDN: begin - SVG). This tells the SVG not to start it until I use JavaScript to trigger it using .beginElement().

<animate
id="mysvgline"
attributeType="xml"
attributeName="stroke-dashoffset"
from="500"
to="0"
dur=".8s"
begin="indefinite"
/>

(Another side note: just thinking aloud here as I write this—I wonder if I can use <noscript> inside of SVG as a no-JS fallback)

Add the IntersectionObserver

It might look like this:

if ('IntersectionObserver' in window)  {
// Recommended: make this selector more specific with a `data-animate-on-visible`
let elements = document.querySelectorAll("svg");

let observer = new IntersectionObserver(entries => {
// quit early if users wants Reduced Motion
let mediaQuery = window.matchMedia('(prefers-reduced-motion: no-preference)');
if(!mediaQuery.matches) {
return;
}

for(let entry of entries) {
if(!entry.isIntersecting) {
continue;
}

// Look for <animate> or <animateTransform> that need JS to start
let beginElements = entry.target.querySelectorAll(`:scope [begin="indefinite"]`);
for(let beginEl of beginElements) {
beginEl.beginElement();

// Unobserve so we don’t re-animate the dead
observer.unobserve(entry.target);
}
}
},
{
threshold: .5 // 50% of element must be visible
});

for(let elem of elements) {
observer.observe(elem);
}
}

Try it yourself

Zach’s ugly mug (his face)

Zach is a builder for the web with Netlify. He created the Eleventy static site generator and is still fixated on web fonts. His public speaking résumé includes talks in eight different countries at events like Beyond Tellerrand, Smashing Conference, CSSConf, and The White House. He is an emeritus of Filament Group, NEJS CONF, and still helps out with NebraskaJS. Read more about Zach »

Previous
Vector? Raster? Why Not Both!
Next
If I work really hard on my Open Graph Images, People will share my Blog Posts

7 Retweets

Thomas AllmerCyberCode Twins👾🪐👾tziNicolas HoizeyJohn Kemp-CruzDavid East🔴 André Jaenisch 🔴
54 Likes
Michael ZumsteinJacob LeechAlexei AccioPaul MeleroRavin SharmaJim Wolfハチ huangMukmin Abd SamadJosé Manuel DíazGeorg AndraeuptonkingMathieu Huotkeith kursonJohan TerpstraNikita Voloboevкг|sтоf вегиаегтEric WallaceMatt BiilmannTorsten KnabeRobTabsLeoaeeSam TancharoensuksavaiChen ZhixiangMatthias OttPaula DietermanSimon WillisonJason LengstorftziNicolas HoizeyAnna YeamanSia KaramalegosHyeseong KimAnikJeremy WynnDavid EastMichael SchultzThomas AllmerDennis FrankCyberCode Twins👾🪐👾Nic ColgrovePelle WessmanBen Delarre大島遼|Ryo Oshimakeith h.garlic salt enjoyerSimon St.LaurentAɴᴅʀᴇᴡ Sᴏʟᴀɴᴛᴏ🔴 André Jaenisch 🔴rong-senJohn Kemp-CruzAndy DaviesChris PortschellerAnthony Sapp
15 Replies
  1. Zach Leatherman

    Zach Leatherman @zachleat #

    wEll THaT was yOUr firsT MIstAke

  2. Jon Kuperman

    Jon Kuperman @jkup #

    I READ IT!!

  3. Zach Leatherman

    Zach Leatherman @zachleat #

    why thank you Jhon I wrote a blog post recently on this very topic

  4. Jon Kuperman

    Jon Kuperman @jkup #

    I love your open graph images so much

  5. Sia Karamalegos

    Sia Karamalegos @TheGreenGreek #

    "save it in my blog brain" is one of the top reasons I write blog posts 😆 I'm always referencing my own posts to remember how to do something

  6. Guus Hoeve

    Guus Hoeve @Bliepjes #

    One thing off the topic of SMIL, is that in SVG it's really sad you can't influence the scale of a displacementmap in the arguments like: ... scale="var(--scale)" ... so you can animate it in CSS. They need hardcoded values. That would change the game of SVG

  7. Guus Hoeve

    Guus Hoeve @Bliepjes #

    In my perception they are the same to SVG's animation attributes. If it's just a difference in name, it's already native I guess? Something we just don't think about anymore? Because otherwise, what is driving SVG animations natively? 😅

  8. Tabs

    Tabs @ladyofcode #

    I didn't bother with it much expecting it to disappear, but I guess now is a good time to dive right in?

  9. Zach Leatherman

    Zach Leatherman @zachleat #

    strange that the Edge switch to Chromium may have saved it? caniuse.com/svg-smil Note the warning on developer.mozilla.org/en-US/docs/Web…

  10. Guus Hoeve

    Guus Hoeve @Bliepjes #

    Forgive me for asking the obvious maybe, but what's the support for SMIL as I read it in Drasner's book SVG animations, but don't see anyone using it or in any animation tooling as export. I love SVG, no doubt, but I do want it to last.

  11. Zach Leatherman

    Zach Leatherman @zachleat #

    Honestly I only recently experimented with it but it’s working great!

  12. Chris Portscheller

    Chris Portscheller @cport1 #

    I really loved SMIL back in the day, but dropped it for a few projects because of this limitation in some enterprise projects. Definitely opens the doors for some new considerations.

  13. Zach Leatherman

    Zach Leatherman @zachleat #

    oH yEaH IT nevEr Left—LOOK AT THiS beAutIful GREeN

  14. Chris Portscheller

    Chris Portscheller @cport1 #

    I guess with IE becoming chromium it's relevant again.. which is awesome <3 I remember asking this on stackoverflow years ago... stackoverflow.com/questions/3192…

  15. Chris Portscheller

    Chris Portscheller @cport1 #

    SMIL is a thing again?

    53 Mentions
    1. Nucléolo

      Nucléolo @Nucleolo_ #

      Fire SVG animations (smil) when the SVG is visible zachleat.com/web/svg-animat… #css #html #js #webdesign #appdesign #productdesign #programming #code #coder #coding #digital #animation #ixd #web #svg #vector #FrontEndDevelopment #Webdesigner #webdevelopment #webdeveloper #webs… Truncated

    2. tipsxd.com #

    3. tipsxd.com #

    4. tipsxd.com #

    5. tipsxd.com #

    6. tipsxd.com #

    7. technologynews.biz #

    8. techupd.com #

    9. techupd.com #

    10. techupd.com #

    11. techupd.com #

    12. techupd.com #

    13. dailytechpage.com #

    14. dailytechpage.com #

    15. dailytechpage.com #

    16. dailytechpage.com #

    17. www.67nj.org #

    18. wpdesigns.live #

      Show original post Had a use case come in where the design had an SVG animation that ran one interation and only one. It looked like this (some content has been removed): If you’re on a device with a small vertical viewport size, you may not have noticed the above animation. Unfortunately the anima… Truncated

    19. wpdesigns.live #

      Show original post Had a use case come in where the design had an SVG animation that ran one interation and only one. It looked like this (some content has been removed): If you’re on a device with a small vertical viewport size, you may not have noticed the above animation. Unfortunately the anima… Truncated

    20. wpdesigns.live #

      Show original post Had a use case come in where the design had an SVG animation that ran one interation and only one. It looked like this (some content has been removed): If you’re on a device with a small vertical viewport size, you may not have noticed the above animation. Unfortunately the anima… Truncated

    21. wpdesigns.live #

      Show original post Had a use case come in where the design had an SVG animation that ran one interation and only one. It looked like this (some content has been removed): If you’re on a device with a small vertical viewport size, you may not have noticed the above animation. Unfortunately the anima… Truncated

    22. COMMENTSENSE

      COMMENTSENSE @sense_comment #

      fIre Svg AnimATionS (SmIL) whEn ThE Svg IS viSiBlE—ZACHlEAt.CoM ZACHleat.COM/WeB/SVg-anIMaT…

    23. wpguynews.com #

    24. wpnewshub.com #

    25. Suzanne Pamela Webb

      Suzanne Pamela Webb @SuzannePamelaW1 #

      Fire SVG aNIMAtionS (sMIl) When the SVg Is VIsibLE—zaCHLEAt.CoM #wEbdeSiGn VIA tWINYBOtS.cH zachLEAt.CoM/weB/SVg-anIMAt…

    26. www.codeificant.com #

      Show original post Facebook Twitter LinkedIn Pinterest … Truncated

    27. www.codeificant.com #

      Show original post Facebook Twitter LinkedIn Pinterest … Truncated

    28. www.codeificant.com #

      Show original post Facebook Twitter LinkedIn Pinterest … Truncated

    29. www.codeificant.com #

      Show original post Facebook Twitter LinkedIn Pinterest … Truncated

    30. www.codeificant.com #

      Show original post Facebook Twitter LinkedIn Pinterest … Truncated

    31. blogs.thebitx.com #

    32. graphicdon.com #

    33. codinghindi.in #

    34. justJANICE1968

      justJANICE1968 @Janice87587731 #

      FiRE SvG aNimatioNS (SmiL) wHen the SVG IS ViSiBle—zAchleaT.cOm #WeBDESign vIa twinYboTs.CH zACHLeAt.COm/wEB/SVG-ANiMaT…

    35. Pawan

      Pawan @PawanSomanchi #

      FIRE SvG aNiMAtIoNs (SmIl) WhEN ThE sVG is vISIbLe—zaCHLEaT.Com #wEBdesIGN via twINYbots.ch zachLeAT.CoM/web/SVg-AnimAT…

    36. pikopong.com #

    37. hnikoloski.com #

    38. gigatechnews.com #

    39. style-tricks.com #

    40. VisionSnap

      VisionSnap @VisionSnap #

      fIrE SVg aNiMaTIONs (SmIL) when tHE SVg is vISIblE cSS TrIcks zaChLEaT.Com/wEB/SVg-aNiMaT…

    41. neoweb4u.com #

    42. websitedevelopment.top #

    43. websitedevelopment.top #

    44. websitedevelopment.top #

    45. websitedevelopment.top #

    46. admin https://www.pixellyft.com/author/admin/ #

      Had a use case come in where the design had an SVG animation that ran one interation and only one. It looked like this (some content has been removed): If you’re on a device with a small vertical viewport size, you may not have noticed the above animation. Unfortunately the anima… Truncated

    47. techsumo.net #

    48. techsumo.net #

    49. techsumo.net #

    50. techsumo.net #

    51. marketingsolution.com.au #

      Show original post Fire SVG animations (SMIL) when the SVG is visible September 8, 2021 Web Development No Comments When requirements read “when visible” your brain should go straight to IntersectionObserver. That’s exactly what Zach is doing here to kick off an animation when i… Truncated

    52. Feedpushr feeds.

      Feedpushr feeds. @feedpushr #

      firE sVG aNImatiONs (SMIL) whEn ThE SvG is viSiBLE zaCHleat.COm/WEB/Svg-ANIMaT…

    53. mailsgun.ru #

    Social Card Image Preview

    This is what will show up when you share this post on Social Media:

    How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)