Small things that happen when you scroll
None of these is a feature. They're the small reactions that make a page feel like it noticed you arrived. I've collected five from my landing page and portfolio, and each one below is running for real: you trigger it by reading this page, the normal way. Nothing here takes the scroll away from you.
The rule I kept to: the page scrolls at the speed you scroll. Effects can respond to it, never steer it.
A wash of colour
On the landing page, pastel boxes start white and a tint sweeps across them, corner to corner, once they're properly on screen. The trick is one oversized gradient: half colour, half white, at 135°, four times the size of the box. Sliding its background-position from the bottom right to the top left drags the diagonal edge across.
cubic-bezier(.33,.9,.3,1), 110ms apart.With reduced motion the boxes are simply their colour from the start.
Ink that follows you
The portfolio has one statement set large, and its words fill in as you scroll down to it. Every word starts at 15% ink. The share of words that are dark is just how far the block has travelled from the bottom of the screen to the middle, so it's finished by the time it's comfortable to read.
It's a scroll listener throttled to one requestAnimationFrame, with no library. On the real page the finish line also shifts so that a jump from the menu never lands you on a half-inked sentence.
Rising from the floor
The career timeline on the portfolio comes up tilted back, as if the cards were lying on a table and being lifted towards you. Each one is tipped by up to 13° and pushed 170px into the screen, and it straightens as it climbs to 60% of the way up the viewport. Then it stays flat. Cards you've already read don't fall away again.
A bakery opens on the corner
It starts a one-page newsletter
Bread by bicycle, three streets each way
A second oven, and a queue
Still open at six every morning
Two details keep it smooth. The progress is eased (10% of the way per frame), so the cards glide instead of tracking your scroll wheel's jitter. And positions are measured from offsetTop, which ignores transforms, so tilting a card can't change where the code thinks it is. On the real site this switches off below 900px wide; here it runs everywhere.
A little shear
Scroll the portfolio fast and its sections lean, as if the page had some weight to it. The lean is the scroll distance since the last frame times 0.02, capped at 0.6° either way, and eased at 12% a frame so it rises and falls rather than flickering.
A section with some weight
Flick the page quickly up and down while this is on screen. Under half a degree is almost nothing, which is the point.
It goes back to perfectly straight when you stop.
When the lean drops under 0.004° and the page has stopped, the loop clears the transform and goes to sleep. Reduced motion skips it altogether.
Rack focus
The last one is borrowed from film. My portrait on the landing page starts out of focus and slightly too close, and as it scrolls in it pulls sharp: blur from 14px to 0, scale from 1.12 to 1.06, over 1.5s with power3.out. It doesn't settle at 1 because it keeps drifting 2.5% against the scroll afterwards, and that extra 6% stops the edges ever showing.

It uses GSAP and ScrollTrigger, which the landing page only fetches when the portrait is about 1,500px away. With reduced motion, or if the scripts never arrive, it's just a picture.
- Built
- August to October 2026
- Stack
- CSS, plain JS, GSAP for the portrait
- Lives at
- thomasalex.in and /portfolio
- Source
index.html,portfolio.html,assets/portrait-fx.js