057

Layered Depth Template

£20 or the whole Vault, £99

A spatial and exhibition design studio site with a photographic depth corridor, a cursor-tilted cluster, and project images that open to full bleed. Suits architecture, interiors, photography portfolios and arts venues.

ScrollTriggerFlip Lenis advanced
8 more details
3d-transformsscrubpinned-sectionparallaxpointer-tiltflip-layoutscroll-revealclick-toggle

This template reads better at your own screen size than in the frame below:

Updated

About this template

Halflight is a complete one-page site for a spatial, exhibition or scenography practice, art-directed as layers in a lit room rather than cards on a page. Content sits on translucent planes at a slight perspective, casting onto each other over a deep indigo ground, with an oversized ghost numeral behind the type and photography breaking the section seams.

Read the full template overview

Three interactions carry it, each on a different input. Scroll carries the visitor through a corridor of photographs, with walls of images and light overhead. A fast flick opens the view and stretches the passing panels before the room eases back to its resting depth. The central type stays sharp and still. The cursor tilts a second cluster, each plane sliding by its own depth with a specular sweep tracking across it. Clicking a plane in the work strip lifts it out of the stack, flattens it to full bleed with its detail, and settles it back into the exact slot it left.

Everything is static HTML, CSS and one script: no build step, no framework. Repaint the five values in the token block to reskin it, drop your own photographs into assets/img, and rewrite the copy. Every section is independent, so any of them can be deleted without touching the JavaScript.

Layered Depth Template - website template preview

What's included

9 items
  • Photographic depth corridor with surrounding image walls, overhead light, a fixed central headline and three progress chapters; fast desktop scrolling opens the view before a spring settle
  • Pointer-tilted plane cluster on fine pointers, with a per-plane depth parallax and a specular sweep, and a designed static three-quarter view on touch
  • GSAP Flip flatten: a plane lifts out of the work strip to full bleed and returns to its exact slot with an elastic settle
  • Full keyboard path for the flatten interaction: real buttons, Enter or Space to open, Escape to close, managed focus
  • Deep indigo, chrome and one warm signal, with every translucent value mixed from --*-rgb triples so a reskin is a five-value edit
  • Designed reduced-motion page: the depth pass resolves into a static row beside its legend and every project detail is open
  • Readable with JavaScript disabled or the CDN blocked, including every project detail
  • Touch keeps a lighter photographic corridor without velocity warp; the hero and pointer cluster use static compositions
  • Lenis smooth scroll wired on the shared GSAP clock, opt-out per page or per URL

Perfect for

5 use cases
  • Exhibition, scenography and spatial design studios presenting rooms rather than screens
  • Architecture and interior practices that need depth and light in the first screen
  • Experimental music venues and arts programmes with a layered, low-light identity
  • Photography and installation portfolios where each project deserves a full-bleed moment
  • Any studio site that needs three distinct interactions rather than one hero animation

How it works

5 sections

The plane stack

The hero builds a real 3D scene: a perspective container, a preserve-3d stack, and planes offset in Z so they cast and tint each other. The headline deliberately lives outside that chain, because a 3D context rasterises type and swallows pointer events. All of the 3D scaffolding is pointer-events: none, and only the interactive children take presses back.

The depth corridor

Photographs surround the visitor as they move through three chapters of the room. Nearby images turn into view, distant images disappear into the room’s colour, and a quick desktop scroll opens the space before it relaxes again. The headline stays still throughout. Touch keeps the journey with a calmer response; reduced motion presents a static strip of the photographs.

Tilting the cluster

On a fine pointer the cursor tilts the cluster on both axes with an eased follow, and each plane slides by its own data-depth so the group opens and closes as the viewing position moves. Leaving the section relaxes it back to the resting three-quarter view over about a second. Coarse pointers keep that view fixed in CSS and never attach the listener.

Flattening a plane

Flip.getState measures the plane in its slot, a class switches it to a fixed full-bleed panel, and Flip.from animates the difference; closing repeats it in reverse so the plane returns to the pixel it left, with a short elastic dip as it beds back in. The strip and the empty slot are height-locked for the duration, or the page below would jump while the plane is out of flow.

Without JavaScript or motion

A synchronous head script adds .has-js before first paint so nothing flashes; the main script removes it again if the CDN is blocked, leaving a plain complete document with every project detail visible. Under prefers-reduced-motion the CSS lays the depth pass out as a static row beside its fully-set legend, holds the clusters at a fixed angle, and opens every detail, and the script's own motion branch restores each gated reveal.

Plugins ScrollTrigger, Flip
Difficulty Advanced
Smooth scroll Lenis integration
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this template's demo, from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Questions about this template

How does the corridor behave on phones?

The photographs still travel through depth, with a lighter scene and a frame sized to keep its chapter labels on screen. Velocity warp is disabled on touch for a calmer response. The separate pointer cluster holds a static composition. Reduced motion shows the photographs as a still contact strip.

What are the three interactions?

A photographic corridor that responds to scroll speed, a pointer-tilted photo cluster with parallax and moving light, and a project image that opens to full bleed and returns to its exact place in the work strip.

Can the flatten be used with a keyboard?

Yes, fully: real buttons, Enter or Space to open, Escape to close, and managed focus. With JavaScript disabled or the CDN blocked every project detail is still readable, and under reduced motion the depth pass resolves into a static row beside its legend with all details open.

What kind of studio is it for?

Ones presenting rooms rather than screens: exhibition, scenography and spatial design, plus architecture and interiors practices that need depth and light in the first screen. Experimental venues and installation portfolios also fit, because each project gets a full-bleed moment.

How hard is it to repalette?

Five values. Deep indigo, chrome and one warm signal, with every translucent value mixed from RGB triples, so there are no stray rgba literals to hunt down when you change the scheme.

Paid template

Purchase to unlock the code.

Buying Layered Depth Template opens the HTML, CSS and JavaScript source, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

£20 Standard license, unlimited projects

Browse free effects

Or the whole library: the Vault, £99, one payment.

Documentation

Quick Start

1. Upload the folder. index.html, assets/style.css, assets/script.js (or assets/script.min.js) and assets/img/ are the whole site. Any static host will do.

2. Check the <head>. Three things must stay, in this order:

Code snippet omitted: it ships with the download.

That one-line script must stay synchronous and stay in <head>. It is what stops every reveal target painting visible for a frame and then flashing to zero. data-cfasync="false" stops Cloudflare Rocket Loader deferring it, which would bring the flash back on the live site only.

3. Keep the scripts before </body>:

Code snippet omitted: it ships with the download.

4. Rewrite the copy and swap the photographs. Everything else is optional.


Sections and their options

Each section is initialised by its own function and every one of them returns early when its markup is missing, so you can delete any section from index.html without touching the JavaScript.

Section Hook What you can change
Hero data-hero The stack is three figure.hplane elements. Their left/top/width/height and translateZ in style.css are the composition; move them freely. The ghost numeral is .ghost-numeral — any one or two characters.
Depth corridor data-depth-section Side ranks (data-corridor-rank="left/right") contain the photographs; top/bottom ranks contain light slats. The script repeats each authored set to fill the measured depth. Edit the three data-depth-item entries to rename the progress chapters.
Practice .practice The pale field. .practice-statement is deliberately pulled off the left edge with a negative margin; keep it three or four short lines.
Field of view data-field Three figure.fplane elements. data-depth on each (0–1.5) sets how far it slides under the cursor: higher means nearer the viewer and more movement.
Rooms data-rooms Copy an article[data-room] block to add a project. Give the new .room-detail a unique id and point the button's aria-controls at it.
Ledger .ledger A plain ordered list. Add or remove li rows.

Motion options on data-depth-section (optional data attributes):

  • data-scroll="2.5": pinned travel in frame heights (touch defaults to 2.8).
  • data-speed="1": travel multiplier; data-drift="18": idle travel in pixels per second, or 0 to park it.
  • data-depth="1800": minimum depth; data-gap="150": spacing between image panels. Each rank can override its gap.
  • data-fov="1000": cruise perspective (touch defaults to 1400); smaller values widen the view. Keep data-near (default 340) below the minimum perspective during warp.
  • data-spread="1": distance of the walls from the centre; data-turn="34": approach yaw in degrees.
  • data-warp="false": disable the velocity response. Touch always disables warp. Desktop fast scrolling widens perspective, stretches panels, lifts haze and reveals streaks, then settles back to cruise.

The caption lives outside the 3D scene so it stays sharp and stationary. Panel repeats are decorative and removed during cleanup; the ticker runs only while the section is in view. The chapter counter follows overall scroll progress, independently of the repeating photographs.

The separate pointer cluster uses 8 degrees of yaw and 6 of pitch (initFieldTilt).


Palette

The reskin is a small edit to one block. Open assets/style.css and change the five solids in :root together with their matching RGB triples:

Code snippet omitted: it ships with the download.

Everything else in the stylesheet — plane fills, scrims, rules, dimmed and faint type, focus rings — is one of those triples at another alpha, so nothing is left mixed from the old colour after a repaint. There are no hardcoded rgba() literals to hunt down.

Contrast was measured as used, composited, at the size it is used, and the figures are recorded in the :root header comment. Two constraints hold the palette in place:

  • Body copy is chrome at 74% over the plane fill, at 5.86:1. Dropping that alpha below about 0.70 takes body copy under the 4.5:1 floor.
  • The warm signal is never text, a rule or a focus ring on the pale field. It measures 1.51:1 there. On that section the accent role is carried by solid indigo instead, which is why .practice :focus-visible overrides the outline colour.

Text on a plane always sits inside the opaque foot of --scrim-plane, so even a blown-out white pixel in the photograph behind it composites to a dark ground and the copy still measures 5.76:1. If you move a caption up out of that band, re-measure it.

The type roles are --font-display (Tomorrow) and --font-body (Sarabun). Display peaks at 96px against a 16px body; that 6:1 ratio is where the sense of depth in the type comes from, so if you raise the body size, raise --step-display with it.


Images

The photographs in assets/img/ are bundled, optimised WebP derivatives with the template's grade already baked into the pixels, which is what makes the set read as one campaign.

To use your own, replace the files with the same names and the same shapes:

File Shape Where it lands
hero-bleed.webp 1920 × 1080 the deepest plane behind the hero stack
plane-01.webp … plane-04.webp 1100 × 1400 the depth pass, the cluster and the work strip

Every image uses object-fit: cover, so a replacement at a different aspect ratio still fills its plane; only the width/height attributes in index.html need updating, and only to keep the browser from reflowing on load. Each plane carries a solid background-color beneath the photograph, so the page looks designed while the images are still downloading. Keep them under about 350KB each.

Photo credits

The originals are royalty-free photographs from Unsplash. What ships in assets/img/ are altered, graded derivatives, not the originals; these are the source files each one was baked from, and re-running the manifest fetches them again.


Accessibility

  • Keyboard. Each work plane is a real <button>: Enter or Space flattens it, focus moves to the close control, Escape closes it from anywhere, and focus returns to the plane it came from. Every hover state has a matching :focus-visible state.
  • Reduced motion. prefers-reduced-motion: reduce gives a designed static page, not the animated one with the motion switched off: the depth pass lays out as a static row of planes beside its legend, with every entry set rather than only the active one, the clusters hold a fixed three-quarter view, and every project detail is open in the document. Nothing is invisible and nothing is reachable only by an animation that never runs.
  • Without JavaScript. The head script's class is removed if GSAP fails to load, so a blocked CDN leaves a plain, complete document with every project detail readable.
  • Touch and small screens. The corridor retains depth on touch with a calmer field of view and no velocity warp. The hero and pointer cluster resolve into static compositions below 900px or on coarse pointers. The pointer tilt is never attached on a touch device; the cluster keeps a styled static angle.
  • Decorative layers. The plane scenes, the ghost numeral and the light gradients are aria-hidden; the words they illustrate live in the legend and the section copy.

Smooth scroll

Lenis is wired to the GSAP ticker so ScrollTrigger and the smooth scroll share one clock. It is opt-out: add data-smooth="off" to the <html> tag to ship without it, or append ?smooth=off to any URL to compare. It is also disabled automatically under reduced motion, which Lenis does not honour by itself. Remove the whole initLenis block and the Lenis <script> tag to drop it entirely; every ScrollTrigger on the page is correct either way.

Dependencies

  • GSAP 3.15.0 — core, ScrollTrigger, Flip
  • Lenis 1.3.17 (optional)
  • Google Fonts: Tomorrow, Sarabun

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.