<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jiant Ramadan</title>
    <description>The latest articles on DEV Community by Jiant Ramadan (@jiant).</description>
    <link>https://dev.to/jiant</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4116211%2F0d220d00-47c0-4e9f-91d9-54a7ec9a0c01.jpg</url>
      <title>DEV Community: Jiant Ramadan</title>
      <link>https://dev.to/jiant</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jiant"/>
    <language>en</language>
    <item>
      <title>Building Motion-Heavy Websites Without Destroying Mobile Performance</title>
      <dc:creator>Jiant Ramadan</dc:creator>
      <pubDate>Tue, 08 Sep 2026 17:40:34 +0000</pubDate>
      <link>https://dev.to/enviory/building-motion-heavy-websites-without-destroying-mobile-performance-57k5</link>
      <guid>https://dev.to/enviory/building-motion-heavy-websites-without-destroying-mobile-performance-57k5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvxbsjrv61u7ygxuce1kl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvxbsjrv61u7ygxuce1kl.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lessons from building animation-heavy web experiences with GSAP, WAAPI, SVG, lazy mounting, and device-aware motion.&lt;/p&gt;

&lt;p&gt;Animation is easy to add to a website.&lt;/p&gt;

&lt;p&gt;Making a website feel heavily animated &lt;strong&gt;without making it feel heavy&lt;/strong&gt; is a different problem.&lt;/p&gt;

&lt;p&gt;I ran into this while building &lt;a href="https://enviory.com/" rel="noopener noreferrer"&gt;Enviory&lt;/a&gt;, a digital wedding invitation platform where motion isn't just decoration. Each invitation is designed more like a small interactive experience: animated typography, layered illustrations, scroll-driven scenes, image transitions, and decorative elements all have to work together.&lt;/p&gt;

&lt;p&gt;On desktop, this is relatively forgiving.&lt;/p&gt;

&lt;p&gt;On a mid-range phone, it isn't.&lt;/p&gt;

&lt;p&gt;A theme that looks perfectly smooth on my development machine can suddenly become a collection of dropped frames, delayed images, and expensive repaints on mobile.&lt;/p&gt;

&lt;p&gt;Over time, I stopped treating animation performance as an optimization step and started treating it as part of the animation architecture itself.&lt;/p&gt;

&lt;p&gt;Here are some of the lessons that made the biggest difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Not Everything Needs an Animation Library
&lt;/h2&gt;

&lt;p&gt;My first instinct was to put most motion behind the same animation system.&lt;/p&gt;

&lt;p&gt;That makes orchestration convenient, but it also means you're reaching for a relatively powerful abstraction even for things the browser can already do extremely well.&lt;/p&gt;

&lt;p&gt;I eventually settled on a simpler division:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS for simple loops and state transitions&lt;/li&gt;
&lt;li&gt;WAAPI for lightweight imperative animation&lt;/li&gt;
&lt;li&gt;GSAP for timelines, complex sequencing, and scroll-driven interactions&lt;/li&gt;
&lt;li&gt;JavaScript only when the animation actually needs application state or runtime calculation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A decorative flower gently floating forever doesn't need a GSAP timeline.&lt;/p&gt;

&lt;p&gt;A sequence where multiple layers enter, overlap, react to scroll position, and hand control to another scene probably does.&lt;/p&gt;

&lt;p&gt;The goal isn't to use the smallest amount of JavaScript possible.&lt;/p&gt;

&lt;p&gt;It's to use the &lt;strong&gt;cheapest tool that still expresses the motion correctly&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Best Optimization Is Sometimes Not Rendering
&lt;/h2&gt;

&lt;p&gt;One of the biggest improvements came from changing how scenes were mounted.&lt;/p&gt;

&lt;p&gt;A long interactive page might contain many sections with images, decorative SVGs, animation timelines, observers, and event handlers.&lt;/p&gt;

&lt;p&gt;Even if most of them aren't visible, they can still contribute to initialization cost.&lt;/p&gt;

&lt;p&gt;Instead of initializing the entire experience immediately, I started treating scenes outside the viewport as future work.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isIntersecting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;mountScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rootMargin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;600px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The extra margin is important.&lt;/p&gt;

&lt;p&gt;Waiting until something actually enters the viewport is often too late. By mounting slightly ahead of the user, expensive work happens before the scene is needed without initializing the entire page upfront.&lt;/p&gt;

&lt;p&gt;This ended up being useful for more than animation.&lt;/p&gt;

&lt;p&gt;It also helped with images, scene-specific logic, and other resources that didn't need to exist during initial render.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. SVG Can Be Surprisingly Expensive
&lt;/h2&gt;

&lt;p&gt;I love SVG for interactive design.&lt;/p&gt;

&lt;p&gt;It's scalable, editable, scriptable, and works beautifully when transferring visual systems from design tools into the browser.&lt;/p&gt;

&lt;p&gt;But "vector" doesn't automatically mean "cheap."&lt;/p&gt;

&lt;p&gt;This became particularly obvious with SVG filters.&lt;/p&gt;

&lt;p&gt;Effects involving things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;feTurbulence&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;feDisplacementMap&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can look harmless in a static design but become surprisingly expensive when the affected element is moving.&lt;/p&gt;

&lt;p&gt;A textured illustration that was perfectly smooth on desktop could become one of the most expensive parts of a scene on mobile.&lt;/p&gt;

&lt;p&gt;My rule became:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep the vector representation when being vector actually provides value.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simple paths, shapes, masks, gradients, and shadows can stay SVG.&lt;/p&gt;

&lt;p&gt;Complex texture/displacement effects that don't need to change dynamically can often be rasterized.&lt;/p&gt;

&lt;p&gt;You lose some theoretical flexibility.&lt;/p&gt;

&lt;p&gt;You gain a much cheaper frame.&lt;/p&gt;

&lt;p&gt;For an effect nobody will edit independently, that's usually a good trade.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Animate Compositor-Friendly Properties Whenever Possible
&lt;/h2&gt;

&lt;p&gt;This one is well known, but it becomes much more important once several animations run simultaneously.&lt;/p&gt;

&lt;p&gt;Prefer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;transform&lt;/span&gt;
&lt;span class="nt"&gt;opacity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;over properties that repeatedly affect layout or paint.&lt;/p&gt;

&lt;p&gt;That doesn't mean every &lt;code&gt;transform&lt;/code&gt; animation is automatically cheap. Huge layers, filters, excessive compositing, and large transparent images can still hurt.&lt;/p&gt;

&lt;p&gt;But it gives the browser a much better starting point.&lt;/p&gt;

&lt;p&gt;I also became much more conservative with &lt;code&gt;will-change&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's tempting to put:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;will-change&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;on every animated element.&lt;/p&gt;

&lt;p&gt;Don't.&lt;/p&gt;

&lt;p&gt;Promoting everything can increase memory usage and eventually work against you. I use it for elements that genuinely benefit from compositor promotion rather than as a global "make animation fast" switch.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Mobile Should Be a Motion Tier, Not a Smaller Desktop
&lt;/h2&gt;

&lt;p&gt;This was probably the biggest architectural change.&lt;/p&gt;

&lt;p&gt;Originally, responsive motion mostly meant adjusting values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;desktop movement: 120px
mobile movement: 70px
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But mobile performance isn't just a question of distance.&lt;/p&gt;

&lt;p&gt;A phone has different constraints: GPU capability, memory, viewport behavior, touch interaction, thermal limits, and potentially battery-saving modes.&lt;/p&gt;

&lt;p&gt;So I started thinking in &lt;strong&gt;motion tiers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A high-performance environment can receive the full experience.&lt;/p&gt;

&lt;p&gt;A constrained device can receive fewer simultaneous effects, simpler transitions, reduced parallax, cheaper decorative animation, or different timing.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;prefers-reduced-motion&lt;/code&gt; remains a separate accessibility concern rather than being treated as a performance mode.&lt;/p&gt;

&lt;p&gt;This means the visual language stays consistent while the implementation cost changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Optimize the Frame, Not the Lighthouse Score
&lt;/h2&gt;

&lt;p&gt;Lighthouse is useful.&lt;/p&gt;

&lt;p&gt;But an animation can pass Lighthouse and still feel terrible.&lt;/p&gt;

&lt;p&gt;For motion-heavy interfaces, I care about questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does scrolling stay responsive while a scene initializes?&lt;/li&gt;
&lt;li&gt;Are images already available when their animation starts?&lt;/li&gt;
&lt;li&gt;Does returning to a previous section trigger expensive work again?&lt;/li&gt;
&lt;li&gt;Are multiple animations competing during the same frame?&lt;/li&gt;
&lt;li&gt;Does an iframe or embedded preview behave differently from the full page?&lt;/li&gt;
&lt;li&gt;Does performance degrade after several minutes of interaction?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of the worst issues I've encountered weren't obvious in a synthetic performance report.&lt;/p&gt;

&lt;p&gt;They were obvious after using the site on an actual phone for thirty seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Design and Performance Can't Be Separate Systems
&lt;/h2&gt;

&lt;p&gt;The biggest lesson wasn't about GSAP, SVG, React, or any particular API.&lt;/p&gt;

&lt;p&gt;It was about workflow.&lt;/p&gt;

&lt;p&gt;If a designer creates an effect without considering how it will be rendered, the developer eventually has to choose between reproducing it faithfully and keeping it performant.&lt;/p&gt;

&lt;p&gt;If performance constraints are part of the design system from the beginning, that conflict becomes much smaller.&lt;/p&gt;

&lt;p&gt;My current workflow is closer to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Design
  ↓
Determine visual primitives
  ↓
Choose rendering strategy
  ↓
Choose motion primitive
  ↓
Define device tiers
  ↓
Implement
  ↓
Test on real mobile hardware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Design → Implement everything → Optimize later
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That small change in thinking has saved me a lot of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building &lt;a href="https://enviory.com/" rel="noopener noreferrer"&gt;Enviory&lt;/a&gt; changed the way I think about web animation.&lt;/p&gt;

&lt;p&gt;I used to think about motion mostly in terms of timing, easing, choreography, and visual hierarchy.&lt;/p&gt;

&lt;p&gt;I still care about all of those things.&lt;/p&gt;

&lt;p&gt;But now I also think about &lt;strong&gt;rendering cost as another design constraint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A beautiful animation that consistently drops frames isn't finished.&lt;/p&gt;

&lt;p&gt;Sometimes the best optimization is a different API.&lt;/p&gt;

&lt;p&gt;Sometimes it's rasterizing one decorative layer.&lt;/p&gt;

&lt;p&gt;Sometimes it's mounting a scene 600 pixels before it's needed.&lt;/p&gt;

&lt;p&gt;And sometimes it's simply deciding that an effect doesn't deserve to run on every device.&lt;/p&gt;

&lt;p&gt;The goal isn't maximum animation.&lt;/p&gt;

&lt;p&gt;It's maximum &lt;strong&gt;perceived experience for the rendering budget you have&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
