Leonxlnx/multilayer-effect: How to Make a 404 Feel Like a Stage Set

A small Next.js experiment that turns parallax, masking, and particle recycling into a convincing illusion of depth.

7 min read • View on GitHub • More from Leonxlnx

A theatrical 404 scene built as a layered stage set, with a foreground hand, a partially hidden figure, separated numerals, and drifting petals. The composition explains how depth can be faked by interleaving flat assets and letting motion make the stack feel physical.
The trick is not 3D geometry. It is layer order, motion weight, and a page that knows how to stand in for a scene.
Key Takeaways

The 404 Is the Product, Not the Error

Most 404 pages apologize. This one performs. It uses a failure state to stage a tiny world: background image, central figure, foreground hand, split numerals, and petals that keep the frame alive. The point is not to distract from the error. The point is to make the error feel authored.

That matters because the page is doing brand work before it does utility work. The viewer reads depth, not just layout. And the depth is not coming from a 3D engine. It is coming from a careful stack of flat things that never stop negotiating with one another.

The Whole Trick Depends on Layer Order

ApproachMotion modelPerformance costDepth controlBest use case
Flat hero with simple transitionsMostly static, a few fadesLowMinimalLanding pages that only need polish
Library-driven motion stackDeclarative animation with a heavier runtimeMedium to highStrong, but more abstractInterfaces with many coordinated transitions
This repo’s manual layered approachLERP plus per-layer multipliersLowPrecise and tactileSmall scenes that need a convincing sense of space

The illusion starts with one pointer position, then fans out into separate offsets. Each layer follows the same target, but not at the same speed.

The stack works because it is interleaved, not merely layered. The background stays back. The figure and hand occupy different planes. The numerals cut through the scene instead of sitting on top of it. That arrangement gives the eye a reason to believe in space before motion even starts.

A close-up mechanical metaphor of three flat panels on rails, each moving with a different weight as a cursor-like point pulls them off center. The image explains that the page's depth effect comes from differential motion and easing, not from 3D geometry.
A single pointer movement becomes depth when each layer obeys a different rule.

The Parallax Engine Is Just LERP and Weighting

In page.tsx, the page does not snap to the cursor. It eases toward it. That interpolation, often written as lerp, is the quiet center of the whole effect. Instead of chasing the pointer directly, the scene glides toward it at a controlled rate, which makes the movement feel weighted rather than twitchy.

const lerp = (current: number, target: number, ease: number) =>
  current + (target - current) * ease;

// one eased motion field, many responses
backgroundX = lerp(backgroundX, targetX * 1, 0.12);
personX = lerp(personX, targetX * 4, 0.12);
handX = lerp(handX, targetX * 12, 0.12);

That is the important move. Every layer shares the same base input, but each one multiplies that input differently. Near objects travel farther. Distant objects lag. Your brain supplies the missing depth cue because the motion is consistent with how space usually behaves.

The Petals Prove the Project Is About Feel, Not Features

Getting Started First, run the development server: Open http://localhost:3000 with your browser to see the result.

Project README, Repository documentation · Leonxlnx/multilayer-effect README

The petal system in Petals.tsx is a good clue to the repo's priorities. It uses a simple class-based particle model, updates position and rotation with browser-native transforms, and recycles petals when they leave the viewport. That means the animation reads as continuous without asking the browser to do wasteful work.

The effect is not trying to be a simulation. It is trying to be convincing. That is a better benchmark for a decorative system. If the viewer feels continuity, the implementation has done its job.

CSS Is Doing More Than Styling Here

The heavy lifting does not live in one obvious animation library. It is spread across the CSS. Masking blends the assets into one another. Gradients and shadows give the digits volume. Fluid type keeps the numerals from feeling bolted on. The stylesheet behaves less like decoration and more like a compositor for the page's visual logic.

.heroDigit {
  text-shadow:
    0 1px 0 rgba(255,255,255,0.3),
    0 8px 24px rgba(0,0,0,0.18),
    0 0 1px rgba(0,0,0,0.6);
  will-change: transform;
}

.layerMask {
  -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
}

That is why the page feels more expensive than it is. The work is distributed. Motion, overlap, masking, and typography all share the burden of creating depth. No single trick has to carry the illusion alone.

This Is a Better Demo of Motion Craft Than a Framework Showcase

What it looks likeWhat it actually isWhy it matters
A flashy 404 pageA disciplined layering exerciseThe page proves that restraint can still feel premium
A framework demoA rendering-pipeline lessonThe interesting part is how the browser is being used
An animation showcaseA system for visual weightThe code teaches motion judgment, not just syntax

The project uses current tools, but its real value is older than the framework. It shows that custom motion can be more expressive than packaged animation when the developer understands composition, easing, and the cost of each moving part. In that sense, the repository is less about Next.js than about taste.

The strongest front-end work often looks simple after the fact. That is the point here. The page feels dimensional because every layer is placed with intent, every movement is weighted, and every CSS decision serves the same illusion.