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.
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
videotag. 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
mutedattribute.
Hide the control bar by omitting the
controlsattribute.
Enable inline playback on iOS with
playsinlineand
webkit-playsinline.
WeChat on Android does not allow autoplay; we trigger playback on
scrollor
touchevents 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><video
muted
src="***"
preload="auto"
playsInline
webkit-playsinline="true"
mtt-playsinline="true"
loop
ref={this.videoRef}
/></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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.