Liking cljdoc? Tell your friends :D

<x-metaball-cursor>

Organic blobs that follow the mouse cursor with varying degrees of latency. When blobs overlap, they stretch and fuse together like mercury drops using an SVG filter metaball technique. An optional Perlin noise border makes the edges shimmer continuously, even when the mouse is still.

Tag

<x-metaball-cursor></x-metaball-cursor>

The component should be placed inside a positioned container. It renders as display: block with pointer-events: none, so it won't interfere with page interactions.

Attributes

AttributeTypeDefaultDescription
blob-countnumber5Number of blobs (2–10)
blob-sizenumber40Base blob diameter in px (10–200)
colorstring#6366f1Blob fill color (any CSS color)
noisebooleanabsentEnables Perlin noise shimmer on edges
noise-scalenumber3Turbulence scale (0.5–20)
noise-speednumber0.02Shimmer animation speed (0.001–0.1)
noise-intensitynumber6Displacement amount in px (1–30)
blurnumber12Gaussian blur radius for fusion effect (4–40)
thresholdstring1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10SVG feColorMatrix values for alpha threshold
palettestringabsentNamed preset or comma-separated CSS colors

Properties

PropertyTypeReflects attribute
blobCountnumberblob-count
blobSizenumberblob-size
colorstringcolor
noisebooleannoise
noiseScalenumbernoise-scale
noiseSpeednumbernoise-speed
noiseIntensitynumbernoise-intensity
blurnumberblur
thresholdstringthreshold
palettearray | nullpalette

Events

None — this component is purely visual and decorative.

Slots

None.

Parts

PartDescription
viewportContainer div with the SVG filter applied

CSS Custom Properties

PropertyDefaultDescription
--x-metaball-cursor-color#6366f1Blob fill color
--x-metaball-cursor-opacity1Overall container opacity
--x-metaball-cursor-z-index9999Stacking order
--x-metaball-cursor-blend-modenormalmix-blend-mode on viewport
--x-metaball-cursor-inset0Viewport inset from host edges

Palette Presets

The palette attribute accepts a named preset or comma-separated CSS colors. When set, each blob gets a different color from the palette (cycling if there are more blobs than colors). When blobs fuse, their colors blend at the junction.

NameColorsVibe
rainbow#ef4444, #f59e0b, #22c55e, #3b82f6, #a855f7Full spectrum
ocean#06b6d4, #0ea5e9, #6366f1, #8b5cf6, #0d9488Cool blues & teals
sunset#ef4444, #f97316, #eab308, #ec4899, #f43f5eWarm reds & oranges
neon#22d3ee, #a78bfa, #f472b6, #34d399, #facc15Vivid electric
ember#dc2626, #ea580c, #d97706, #b91c1c, #f59e0bFire tones

Custom colors: palette="hotpink, cyan, gold"

How It Works

  1. Blob divs (circles via border-radius: 50%) are positioned absolutely inside a viewport container.
  2. Each blob follows the mouse via linear interpolation (lerp) in a requestAnimationFrame loop. The lead blob follows quickly (~0.3 speed factor), trailing blobs follow progressively slower.
  3. An SVG filter is applied to the viewport container:
    • feGaussianBlur blurs all blob shapes together.
    • feColorMatrix thresholds the alpha channel — only areas where blurred blobs overlap (high combined alpha) survive, creating the organic fusion effect.
  4. When noise is enabled, feTurbulence + feDisplacementMap distort the thresholded output. The turbulence seed advances each frame, creating constant edge shimmer.

Tuning the Effect

  • Tighter fusion: Increase blur (more overlap needed) or increase the alpha multiplier in threshold (e.g., ... 0 0 0 30 -15).
  • Looser, softer blobs: Decrease blur or lower the alpha multiplier.
  • More shimmer: Increase noise-intensity and noise-scale.
  • Subtle shimmer: Use low noise-intensity (1–3) with moderate noise-scale.

Accessibility

  • The component sets aria-hidden="true" and role="presentation" — it is purely decorative.
  • pointer-events: none ensures it never blocks interaction.
  • When prefers-reduced-motion: reduce is active, the animation loop does not start. Blobs remain static at position (0, 0).

Examples

Basic usage

<div style="position: relative; height: 300px;">
  <x-metaball-cursor></x-metaball-cursor>
</div>

Custom color and size

<x-metaball-cursor color="#ec4899" blob-size="60" blob-count="3">
</x-metaball-cursor>

With noise shimmer

<x-metaball-cursor noise noise-intensity="10" noise-speed="0.03">
</x-metaball-cursor>

CSS custom property override

.hero:hover {
  --x-metaball-cursor-color: hotpink;
  --x-metaball-cursor-blend-mode: screen;
}

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close