🔍

✨ Thorny Particles

Fairy Godmotha dust for dat azz.

Usage

Basic usage with default settings:

<thorny-particles></thorny-particles>

With custom configuration:

<!-- Reduce clustering at cursor and limit pool size -->
<thorny-particles spawn-radius="30" max-particles="100"></thorny-particles>

The component auto-registers via the fungal framework. Simply include the tag anywhere on your page to enable particle effects.

Attributes

  • spawn-radius (optional, default: 0): Radius in pixels for random spawn offset from cursor position. Use a non-zero value (e.g., 20-50) to avoid clustering directly under the cursor.
  • max-particles (optional, default: 200): Maximum number of active particles at once. Lower values reduce particle pool size and improve performance on slower devices.

Demo

You are looking at it.

Features

  • Light DOM: All particles are appended directly into the element (no shadow DOM)
  • Performance: GPU-accelerated transforms, particle pooling, configurable particle limit
  • Accessibility: Respects prefers-reduced-motion media query
  • Visual: Spiral motion with ease-out, fade-out, rotation, and scale animations
  • Theme integration: Uses mix-blend-mode: difference to blend with any theme
  • Configurable: Control spawn clustering and particle pool size via attributes

Behavior

On pointer/mouse movement:

  • Spawns 3-7 particles per move
  • Each particle uses a random glyph: *, +, ·, ✶, ✺, ☼, ♠, ♣, ♥, ♦, 🔮, ✨, 🌀, 🍄
  • Particles spawn at cursor position (or within spawn-radius if set)
  • Particles animate in a spiral pattern outward from spawn point
  • Particles fade out and shrink over 300-700ms lifetime
  • DOM elements are recycled from a pool for efficiency

Examples

Subtle effect with less clustering:

<thorny-particles spawn-radius="25" max-particles="150"></thorny-particles>

Performance mode for slower devices:

<thorny-particles spawn-radius="40" max-particles="50"></thorny-particles>

Technical Details

  • Position: Fixed overlay covering entire viewport
  • Z-index: 9999 (always on top)
  • Pointer events: None (doesn't interfere with page interaction)
  • Animation: RequestAnimationFrame loop, stops when no particles exist

components published