Component · preloader
Preloader
A loader that counts the bytes really received for your model, light and images, skips itself when the files are cached, and leaves with a two-panel wipe while the page rises in.
Vanilla JS1.8 KBReal progressNo flashReduced motion
It counts real bytes.
This page loaded the four files on the right before showing itself: a 560 KB 3D model, a studio HDRI and two images. The number is the share of bytes that actually arrived. If they come from the cache in under 350 ms, you never see the loader at all.
- binoculars.glb560 KB
- studio_1k.hdr1.6 MB
- thumb.webpimage
- thumb.webpimage
Use it
Copy the folder preloader/ (the .js and .css files) into your project. No build step and no framework.
Behaviour
- Progress is real: bytes received out of the total, streamed with
fetch; it holds at 92 until every file reports its size, so it never runs backwards. - Never flashes: fast or cached loads skip the loader entirely.
- Uses the normal HTTP cache, so your 3D code that loads the same files afterwards gets them instantly.
- Announced politely to screen readers (
role="status",aria-busy); the moving number isaria-hidden. prefers-reduced-motion: no counting animation, a short fade instead of the wipe.
Credits
- Real-progress loaders with a panel exit are common on WebGL award sites such as Lusion and Igloo Inc. Sujon's Drive guide asks for loaders that show real progress, never a fake bar. Written from scratch.
- Files loaded: "Binoculars" by Derek Wight and the studio HDRI, both Poly Haven CC0 1.0; images are Zyqor renders.
<link rel="stylesheet" href="preloader.css">
<div class="pl" role="status" aria-live="polite" aria-label="Loading"
data-assets='["/models/hero.glb","/hdri/studio_1k.hdr"]' data-once>
<div class="pl-panel top"></div><div class="pl-panel bot"></div>
<div class="pl-inner">
<div class="pl-word">Brand</div><div class="pl-num" aria-hidden="true">000</div>
<div class="pl-bar"><i></i></div><div class="pl-status">Loading</div>
</div>
</div>
<main class="pl-rise">...</main>
<script type="module">
import { preloader } from './preloader.js';
await preloader(); // then start your 3D scene: the files are in the HTTP cache
</script>| Option | Default | What it does |
|---|---|---|
| data-assets | [] | Files to wait for (models, HDRIs, hero images). Fonts can be added too. |
| data-once | off | Show only once per browser session. |
| minTime (JS) | 900 | Minimum time on screen once it is visible, so it never blinks. |
| .pl-rise | Add to content that should rise in after the loader leaves. |