When Your Beautiful Background Betrays You on Mobile

July 29, 2025 (4d ago)

UI and UX challenges

"Why does my gorgeous branch animation work perfectly on desktop but flicker like a broken TV on mobile?"

Me, at 1am, frantically scrolling through my portfolio on my phone while my laptop showed everything working perfectly.

The Tale of Two Backgrounds

My portfolio had a personality disorder. Some pages had this cool InteractiveSpider animation (think animated web/network effect), others had ArtPlum (beautiful growing branches). It looked like two different websites depending on which page you landed on.

The Chaos:

Users were getting whiplash navigating between pages. Time to pick a side.


Decision: ArtPlum for All (Almost)

I decided to standardize on ArtPlum everywhere except the maintenance page. Why?

The Main Page Makeover

Before:

<InteractiveSpider />
<div className="relative z-10 flex justify-center items-center min-h-[100dvh] p-4">
  <div className="bg-white/60 dark:bg-black/40 backdrop-blur-md rounded-xl shadow-lg">
    {/* Floating card effect */}
  </div>
</div>

After:

<ArtPlum />
<main className="max-w-2xl md:max-w-3xl lg:max-w-4xl mx-auto py-16 px-4">
  <div className="flex flex-col space-y-10">
    {/* Clean, consistent layout */}
  </div>
</main>

Perfect! Consistent layout, same responsive breakpoints, unified visual language. Ship it! 🚀


Plot Twist: Mobile Said "Nope"

Everything looked amazing on desktop. Then I tested on mobile and... chaos.

The Bug:

Meanwhile, desktop users enjoyed smooth, persistent branch animations that stayed put once grown.


Detective Mode: Finding the Culprit

After some debugging, I found the villain: Mobile browsers love triggering resize events.

Why mobile browsers are sneaky:

Every resize event was restarting my ArtPlum animation. Desktop? Rarely resizes. Mobile? Resizes every time you breathe.


The Fix: Smart Resize Detection

I built a mobile-aware resize system that actually thinks before acting:

1. Device Detection + Smart Thresholds

// Detect mobile devices
const isMobile = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
 
// Mobile-specific thresholds  
const threshold = isMobile ? 100 : 50;      // Higher threshold for mobile
const debounceTime = isMobile ? 300 : 150;  // Longer debounce

2. Significance Check

// Only update on REAL size changes
const significantChange = 
  Math.abs(newWidth - lastWidth) > threshold ||
  Math.abs(newHeight - lastHeight) > threshold;

3. Animation State Tracking

// Don't restart unless actually necessary
const isFirstRun = !initialized.current;
const sizeChanged = size.width !== lastSize.width || size.height !== lastSize.height;
 
if (isFirstRun || (!stopped.current && sizeChanged)) {
  start(); // Only restart when needed!
}

4. Mobile CSS Optimizations

.tree-artplum-bg {
  /* ... existing styles ... */
  /* Mobile optimizations */
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  transform: translateZ(0); /* GPU acceleration */
  will-change: auto;        /* Performance boost */
}

The Results

Before Fix:

After Fix:

What triggers restarts now:


Technical Deep Dive: The Fix Strategy

Problem Analysis

  1. Root Cause: Mobile browsers fire resize events aggressively
  2. Impact: Animation restarts on every scroll/touch interaction
  3. User Experience: Flickering, inconsistent visual behavior

Solution Architecture

  1. Smart Detection: Device-aware thresholds and timing
  2. State Management: Track initialization and meaningful changes
  3. Performance: Debouncing and GPU acceleration
  4. Fallback: Graceful handling for edge cases

Code Changes


Lessons Learned

  1. Test on real devices - Chrome DevTools mobile simulation isn't enough
  2. Mobile browsers are different beasts - they optimize aggressively
  3. User experience consistency matters more than perfect animations
  4. Performance and UX often require device-specific approaches

TL;DR


"Good UX is invisible. Bad UX makes users seasick.
Always test on the potato phone, not just the MacBook Pro." 📱✨