Waiting, nicely

Every site makes you wait somewhere: for the fonts, for the big photo, for the next page. I'd rather the waiting looked like it was on purpose. These are the loading screens and page handoffs on my site, roughly in the order I made them, with what each one taught me about the next.

Every demo below has its own Replay button, so you don't have to reload anything.

From nothing

The portfolio opens on two words in a light italic, "from nothing", and a counter that runs from 000 to 100 underneath. When it hits 100 the screen fades and lifts 3% while the headline rises in behind it, a line every 110ms.

0.9s the first time, 0.35s after that. The counter eases out, so the last few numbers slow down.

The first version in July counted in a straight line for 1.3 seconds, every single time. That's fine once. On the fourth page view it's a toll booth. Now the counter eases out with a cubic, and a flag in sessionStorage remembers you've seen it, so a repeat visit gets a 0.35s version and the headline appears without its rise.

The hairline

The landing page has photos, two typefaces and a fair amount of layout, so it gets a proper loading screen: the logo breathing, a 120px hairline filling underneath, and a name in small uppercase mono. It waits for three things, the page, its fonts and the first hero photo, or 8 seconds, whichever comes first. A loader that can trap someone is worse than no loader.

The hairline is a small lie. It fills over 5 seconds on a curve that rushes early and crawls late, and it never goes past 92%. The screen fades out when the page is actually ready, wherever the line has got to.

A small site
Turn "Hold entrances" off and replay: the page's own animations play behind the loading screen, and you see a finished page instead of an arrival.

That caption is the bug I hit. The page's own entrance animations start the moment the HTML arrives, so they had all finished, unseen, behind the loader. The fix is one rule that pauses every animation on the page while the loading class is on, except the loader's own:

html.ld *{animation-play-state:paused!important}
html.ld #loader,html.ld #loader *{animation-play-state:running!important}

Nothing has to know about the loader. Every animation just waits at frame zero and starts when the class comes off.

A quiet placeholder

The hero photo gets a smaller version of the same idea: a soft grey panel with a band of light sweeping across and the logo pulsing, then the photo fades in over 0.8s once it has arrived. The nice part is the delay. The placeholder itself fades in only after a 0.25s grace, so on a fast connection it never appears at all, and you never see a flash of loading for a photo that was already there.

Try the 150ms one: the photo just appears. The delay here is simulated; on the site it's the real download.

The paper wipe

The landing page is white and the portfolio is a warm off-white, #faf9f7. Jumping straight from one to the other felt like a cut in a film where someone forgot the transition. So clicking through to the portfolio first wipes the landing page with the portfolio's paper, from the bottom up, over 0.65s on cubic-bezier(.65,0,.25,1). At 620ms, just before the wipe finishes, the browser is sent on its way.

Click the dark bar. In the demo the "next page" is drawn in the same box instead of loading.

A wipe only hides a load if the load is quick, so the landing page also asks the browser to get the portfolio ready in advance:

<script type="speculationrules">
{"prerender":[{"source":"list","urls":["/portfolio"],"eagerness":"moderate"}]}
</script>

With moderate eagerness, Chrome starts prerendering once you hover the link for a moment, so by the time the paper has covered the screen the next page is often already there. Modifier-clicks skip the wipe so a new tab still opens normally, and the back button clears it.

The concept's curtain

For comparison, here's the loud version from a concept page that never went live: a huge counter in the corner counts to 100 while a hairline fills, over 1.9s, then the whole screen slides up and away (1.1s, power4.inOut) while the headline rises line by line. Leaving pulls a dark curtain up from the bottom before the next page loads.

GSAP, as on the concept. Press Leave for the curtain.

It's well made, and it's three seconds of me before you get to read anything. The sites I like make you wait less and tell you less about it. That's where the quiet ones above came from.

Built
July to October 2026
Stack
CSS, plain JS, GSAP on the concept
Lives at
thomasalex.in and /portfolio
Source
assets/loader.js, assets/hero-ready.js, index.html, portfolio.html

Built with Claude Code. The Replay buttons, the network chips and the "Hold entrances" switch are additions for this page.