A zero-dependency WebGL soap-bubble screensaver for your website. Physically based thin-film light interference.
- Single file — ~14 KB
- WebGL 1.0
- Idle-aware — optional screensaver mode: bubbles appear after a configurable idle delay and vanish on any activity
- Add a canvas to your page:
<canvas id="bubbles-overlay"></canvas>- Style the overlay (fixed, full-viewport, click-through, fading):
#bubbles-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
pointer-events: none; /* bubbles never block your UI */
opacity: 1;
transition: opacity 0.8s ease; /* used for the show/hide fade */
}- Load the script and drive it:
<script src="bubbles.js"></script>
<script>
Bubbles.init({ canvas: '#bubbles-overlay' });
Bubbles.show();
</script>That's it. You can also install via jsDelivr without cloning anything:
<script src="https://cdn.jsdelivr.net/gh/VladIftime/bubbles/bubbles.js"></script>Creates and starts an instance. Returns the instance, or null if WebGL is unavailable or the user has prefers-reduced-motion: reduce set.
| Option | Type | Default | Description |
|---|---|---|---|
canvas |
string / element | '#bubbles-overlay' |
Canvas element or CSS selector for it |
idleDelay |
number | 4300 |
Milliseconds of inactivity before auto-show (idle mode only) |
autoIdle |
boolean | false |
Start the idle cycle immediately (screensaver mode) |
Shows the bubbles and starts the render loop.
Hides the bubbles and stops the render loop instantly (the last frame is dissolved by the CSS fade). If the idle cycle is active, the idle timer is re-armed.
Stops everything and detaches all listeners. Recover memory by releasing your reference.
Arms the idle timer — bubbles appear after idleDelay ms of inactivity. Any mouse / keyboard / scroll / touch activity hides them again and re-arms the timer. This is what autoIdle: true calls internally.
Dispatched on document:
| Event | When |
|---|---|
bubbles-show |
Bubbles become visible |
bubbles-hide |
Bubbles are hidden |
Use them to coordinate with the rest of your UI (e.g. swap text while the screensaver plays — the vladifti.me portfolio uses them to sync a typewriter header).
Each bubble is rendered with the method described by Iwasaki et al. (CGI 2004):
- Spectral interference — for every wavelength from 380–780 nm, the reflectivity of the soap film is computed from the thin-film interference equations (perpendicular and parallel polarization, film thickness 150–1200 nm, refractive index 1.33). The results are precomputed once into a 256×256 lookup texture indexed by (film thickness, viewing angle).
- Two-pass GPU blend — per frame, bubbles are rendered into an off-screen framebuffer in two passes implementing
Lp = (1 − R)·Lit + R·Lir: one pass accumulates the transmitted light, one the reflected interference color, blended with multiplicative/additive blending exactly as in the paper. - Surface detail — a per-bubble fBm normal perturbation simulates the constantly shifting soap film, animated over time.
Physics (drift, buoyancy, bounce, bubble–bubble collisions, spawn/fade lifecycles) keeps the bubbles in view and moving like the real thing.
- Kei Iwasaki, Keichi Matsuzawa, Tomoyuki Nishita — "Real-Time Rendering of Soap Bubbles Taking into Account Light Interference." Computer Graphics International 2004 (CGI 2004), pp. 344–348, University of Tokyo. dblp record
- Windows Vista Bubbles screensaver (© Microsoft) — visual inspiration; this project is an independent WebGL implementation of the CGI 2004 paper.
- vista.css — github.com/VladIftime/vista.css (MIT) — the demo page's window, buttons, and wallpaper are styled with vista.css, loaded from its GitHub Pages site (
https://vladiftime.github.io/vista.css/). The background image is the Windows Vista default wallpaper and the title-bar icon is a Windows Vista system icon (© Microsoft), both used for demo purposes only. - Originally developed for the vladifti.me portfolio.
The demo is published with GitHub Pages via a GitHub Actions workflow (.github/workflows/deploy.yml) — same setup as the vista.css project. To enable it on your fork: Settings → Pages → Source → GitHub Actions (the workflow sets it up automatically on first run), or deploy the branch manually. The demo URL is https://<user>.github.io/bubbles/.
MIT — see LICENSE. The bubbles code is free to use in personal and commercial projects. The demo wallpaper and title-bar icon are © Microsoft assets used only for demonstration.
