Vespertine

Guide · how it was made

the hour, explained

Vespertine is a fictional maison de parfum selling three extraits for the hours after sunset. The audience is fragrance-literate and allergic to hard selling; the page's single job is to make each scent feel like a specific depth of evening — before a single price is read.

Concept

Scent is invisible, so the site renders it as the one thing dusk actually gives you: colour losing its edges. Every fragrance is a chord — a set of six colours with its own breathing tempo — and the entire page sits on one continuous colour-field that reorchestrates as you scroll from perfume to perfume. Nothing is photographed because nothing could be: the product is an hour.

Palette

Type

Cormorant Garamond · italic 300 — display & body

Pénombre, Braise Rose

Fashion-house display serif set enormous, tight and italic. The light weight at huge sizes reads as vapour — the letterforms themselves thin out like scent. Body copy runs at 400–500 so it stays solid at reading sizes.

Jost · 400 — letterspaced caps labels

Sunset +0:22 · Civil dusk

Geometric sans tracked out to .3em for eyebrows, hours, prices and the sunset ticker. It plays the role of the blind-embossed hour on the flacon: quiet, exact, tactile.

Techniques

The signature — the breathing colour-field. A single fixed canvas renders six orbs as additive radial gradients (globalCompositeOperation:'lighter'). The canvas is deliberately tiny — about a sixth of viewport resolution — then upscaled and blurred 42–84px in CSS, so the GPU does the softening and the raster cost stays trivial. Each orb breathes on its own sine phase; each fragrance is a chord object of six colours plus a tempo (Pénombre breathes slow, Braise Rose quick, Ambre Nocturne slowest). An IntersectionObserver watches a centre band of the viewport and, per section, eases every orb's RGB and the global tempo toward the new chord with exponential smoothing — the reorchestration is a crossfade in colour and rhythm, never a cut.

Around it: GSAP + ScrollTrigger choreograph one reveal sequence per section (rise + fade, power3.out, 0.11s stagger) and a slow parallax on fragrance names; note pyramids are translucent backdrop-blur veils that stack like layered organza; buttons are magnetic via gsap.quickTo; grain is a 140px canvas-generated noise tile; hovering any raw material flares a soft orb of that note's colour into the field. No raster assets anywhere — canvas, CSS gradients and type only. The page stays fully readable if GSAP or canvas fail.

Iteration log

  1. Pass 1Craft

    • Lifted the hero gradient endpoint from 50% to 55% alpha mauve so the dimmest letters of “vespertine” hold 3:1 against the base at display size.
    • Unified the veil hairlines onto the single border token — they had drifted to their own rgba value — and pushed all Cormorant reading copy (descriptions, notes, atelier facts) from 400 to 500, because the face goes vaporous below display sizes over an animated field.
    • Evened the vertical rhythm: the atelier's top padding was 20vh against the fragrances' 16vh for no arguable reason; now one value.
    • Added the missing theme-colour meta so the browser chrome sits in the same near-black.
  2. Pass 2Depth

    • Chord preview: hovering a fragrance in the hero index now rehearses that perfume's chord in the field, and releases back to the scroll-position chord on leave — you can “smell” all three from the top of the page.
    • The hero word now arrives blur-to-focus (16px → 0 over 2.2s) alongside its rise — dusk resolving into a word.
    • Enlarged fragrance names to 9.5vw with a −22% overhang margin so “Braise Rose” genuinely crosses into its note pyramid at desktop widths — the overlap was theoretical before.
    • Retuned section reveals from power3/1.25s/0.11 to power4.out/1.4s/0.13 — a longer glide with a softer landing.
  3. Pass 3Hardening

    • 375px: names drop their overhang, pyramids tighten their step from 7% to 4% so the base veil keeps a readable measure, ticker hides, grids collapse.
    • Added min-width:0 to both grid children so the oversized names overflow by design instead of silently widening the track; svh gets a vh fallback.
    • Reduced motion re-verified: no rAF loop at all — the field paints one static frame per chord change; flares, preview, magnetics and parallax never bind.
    • Chanel rule: removed the glow shadow under the hero chord dots — the field behind them already glows; the ornament was repeating it.