Frontend Development 10 min read

Why We Chose HTML Video Over Lottie for a Complex Web Animation

This article examines how a complex brand‑page animation was implemented by evaluating GIF, Lottie, APNG, and HTML video options, ultimately choosing a lightweight MP4 video and detailing the numerous mobile‑browser compatibility challenges and React code needed to achieve reliable autoplay.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Why We Chose HTML Video Over Lottie for a Complex Web Animation

In the Penguin Tutoring brand page we needed to implement a complex animation that plays when the page scrolls into view.

We considered several frame‑animation solutions:

GIF animation – simple but low quality for large, detailed animations, so it was discarded.

Lottie – uses bodymovin to export After Effects animation as JSON and renders with lottie‑web. Initial tests showed color, tilt and dash‑line differences, so we abandoned it for this case.

APNG – provides better quality than GIF but the files were huge (29 MB) and required a polyfill for browsers that do not support it.

HTML video element – a lightweight MP4 (≈350 KB) that meets the visual requirements.

After trials we chose the

video

tag. The implementation needed to address several compatibility issues on mobile browsers:

Autoplay is blocked on Safari and Chrome unless the video is muted; we add the

muted

attribute.

Hide the control bar by omitting the

controls

attribute.

Enable inline playback on iOS with

playsinline

and

webkit-playsinline

.

WeChat on Android does not allow autoplay; we trigger playback on

scroll

or

touch

events and fall back to a frame‑by‑frame image sequence when autoplay fails.

Some Android browsers return a resolved promise from

video.play()

even though the video does not start (e.g., Huawei Honor 8 in WeChat).

Key code snippets (React example):

<code>&lt;video
  muted
  src="***"
  preload="auto"
  playsInline
  webkit-playsinline="true"
  mtt-playsinline="true"
  loop
  ref={this.videoRef}
/&gt;</code>
<code>playVideo = () => {
  const { isVideoCanAutoPlay, isPlayedVideo } = this.state;
  const videoDom = this.videoRef.current;
  if (videoDom && !isPlayedVideo && isVideoCanAutoPlay) {
    const playPromise = videoDom.play();
    if (playPromise) {
      playPromise
        .then(() => {
          this.setState({ isPlayedVideo: true });
        })
        .catch(err => {
          badjs.info(`[Brand Page][AI VIDEO]: autoplay error ${err}`);
          ++this.catchVideoErrorCount;
          if (this.catchVideoErrorCount >= 2) {
            this.setState({ isVideoCanAutoPlay: false });
          }
        });
    }
  }
};</code>

Final takeaways:

Mobile web video autoplay is unreliable, especially on Android browsers.

If autoplay is blocked, user interaction (touch) is required to start playback.

The

video.play()

promise may resolve without actual playback on some devices.

frontendlottieReactmobile compatibilityweb animationhtml video
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.