Liquid Orb Navigation is an interactive liquid-style navigation experience built with SVG, Vanilla JavaScript, and Metaball / Gooey effects.
A black liquid orb floats in the center of the page. Its boundary continuously deforms and reacts to the pointer with localized attraction.
When the pointer enters the main orb, it naturally splits into five menu orbs through a Metaball / Gooey effect. Slow movement produces a delayed surface bulge, while fast movement around the circumference gradually switches to an Agitation / Ripple Mode.
Clicking a menu orb now starts a full-screen liquid page transition:
- The selected orb softens and spreads like cream.
- Its animated SVG path expands beyond all four viewport edges.
- After the screen is fully covered, the matching standalone HTML page opens.
- Returning to the menu reverses the transition and contracts the liquid back into the original orb.
For the most consistent cross-page behavior, serve the repository with a local static server instead of opening files directly:
python -m http.server 8000Then open:
http://localhost:8000/
Modern versions of Chrome, Edge, and Firefox are recommended.
- Slowly approach the outer edge of the main orb.
- Move around the orb boundary at low speed to observe the delayed bulge.
- Sweep quickly around the circumference to trigger agitation and ripple trails.
- Move the pointer inside the main orb to split it into five menu items.
- Click a menu orb to open its standalone page through the cream-like transition.
- Use Back to menu or press
Escon a detail page to return.
| Orb | Page |
|---|---|
| ABOUT | about.html |
| STUDY | study.html |
| PROJECT | project.html |
| GAME | game.html |
| MUSIC | music.html |
The detail pages share detail-page.css and detail-page.js, while keeping their content in separate HTML files.
index.html Main liquid-orb navigation and transition engine
liquid-orb.config.js Visual and animation configuration
about.html About page
study.html Study page
project.html Project page
game.html Game page
music.html Music page
detail-page.css Shared detail-page layout and responsive styles
detail-page.js Shared entrance animation and Esc-to-return behavior
README.md English documentation
README.zh-CN.md Chinese documentation
- Edit
liquid-orb.config.jsfor global visual and animation settings. Its default values reproduce the current demo. - Edit
menuDefsinindex.htmlto change labels, positions, seeds, or destination files. - Replace each detail page's example copy and cards with real content.
- Keep each detail page's
?return=<name>value aligned with its correspondingmenuDefsentry so the reverse transition contracts into the correct orb.
The shared detail-page background is defined by --detail-page-background in detail-page.css. The menu reads this value directly: opening transitions blend from the orb color into the detail background, while return transitions blend back from the detail background into the orb color. This also works when the demo is opened through file://.
window.LIQUID_ORB_CONFIG = {
background: {
type: "color",
value: "#ffffff",
fallbackColor: "#ffffff",
size: "cover",
position: "center center",
repeat: "no-repeat"
},
orbs: {
sizeScale: 1,
color: "#000000",
mouseAttractionStrength: 1
},
animation: {
fps: 60,
splitDuration: 1600,
mergeDuration: 1600,
orbMeltDuration: 1280,
orbReturnDuration: 1040
}
};All configuration parameters:
| Group | Parameter | Accepted values | Default | Description |
|---|---|---|---|---|
background |
type |
"color", "gradient", "image" |
"color" |
Selects how the page background is rendered. |
background |
value |
CSS color, CSS gradient, or image path | "#ffffff" |
Its meaning follows type. Image paths are relative to index.html. |
background |
fallbackColor |
Any CSS color | "#ffffff" |
Color behind a gradient/image and while an image is loading. |
background |
size |
Any CSS background-size value |
"cover" |
Controls image/gradient sizing. |
background |
position |
Any CSS background-position value |
"center center" |
Controls background alignment. |
background |
repeat |
Any CSS background-repeat value |
"no-repeat" |
Controls background tiling. |
orbs |
sizeScale |
0.1–4 |
1 |
Uniform size multiplier for the main orb and all menu orbs. |
orbs |
color |
Any CSS color | "#000000" |
Shared color of the main orb, menu orbs, and liquid page transition. |
orbs |
mouseAttractionStrength |
0–4 |
1 |
Pointer deformation strength; 0 disables attraction. |
animation |
fps |
1–240, or "display" |
60 |
Numeric values set a frame-rate cap. "display" removes the cap and follows the active display through requestAnimationFrame. |
animation |
splitDuration |
16–60000 ms |
1600 |
Main-orb split duration. |
animation |
mergeDuration |
16–60000 ms |
1600 |
Menu-orb merge duration. |
animation |
orbMeltDuration |
16–60000 ms |
1280 |
Duration for a clicked menu orb to cover the screen. |
animation |
orbReturnDuration |
16–60000 ms |
1040 |
Duration for the return transition to contract into its source orb. |
To follow the current display refresh rate, use:
animation: {
fps: "display",
splitDuration: 1600,
mergeDuration: 1600,
orbMeltDuration: 1280,
orbReturnDuration: 1040
}The browser automatically adjusts requestAnimationFrame when the page runs on a different display. The active mode is exposed as data-orb-fps on the root <html> element.
Background examples:
// Solid color
background: { type: "color", value: "#f4f4f5" }
// Any valid CSS gradient
background: {
type: "gradient",
value: "linear-gradient(135deg, #ffffff 0%, #bfdbfe 100%)"
}
// Image path relative to index.html
background: { type: "image", value: "./images/background.jpg" }Animation durations use milliseconds; smaller values make the motion faster. Reduced-motion preferences continue to shorten page melt and return transitions automatically. Invalid or missing values fall back to the original demo defaults.
The animation engine includes several runtime optimizations while preserving the original liquid behavior:
- Full path rendering can use a fixed FPS cap or follow the active display refresh rate.
- Animation pauses while the browser tab is hidden and resumes without a large time-step jump.
- Circle sampling adapts to the device at 64, 72, or 96 points based on CPU cores, available device memory, pixel ratio, and reduced-motion preferences.
- The Gooey filter remains active throughout splitting and merging to avoid visible contour-size jumps.
- Blob point buffers and Ripple objects are reused to reduce per-frame garbage collection.
- Fixed circle angles, sine/cosine values, DOM references, and media queries are cached once during initialization.
The selected sample count is exposed as data-orb-points on the root <html> element for debugging.
- Detail pages support
Escto return to the menu. - Reduced-motion preferences shorten page and liquid transitions.
- Text remains outside the Gooey filter to preserve readability.
MIT License.