The ez-mouse-trail is a high-performance web component designed to create
interactive particle effects. It leverages the Material Symbols variable font
system and a custom modifier engine to allow for complex animations like
gravity, friction, and orbital paths. (Hover your mouse over the following box)
Implementation (Web-Component)
After you have installed your web-component you need to know how to add the mouse trail to your HTML.
Crucially, the ez-mouse-trail does not listen to global mouse events. Instead, it listens to the mouse events of its parent container. This allows you to scope the trail effect to specific sections of your UI or to specific pages without interference.
Since the trail should typically appear on top of your content, you need to stack them. While position: absolute or flex are valid, using a CSS Grid stack is the most robust way to ensure both the content and the trail share the exact same space.
Layout Pattern: Grid Overlay
<div
style="display: grid; grid-template-columns: 1fr; width: 100%; height: 400px; border: 1px solid #333;"
>
<div style="grid-area: 1 / 1; padding: 20px; z-index: 1;">
<h1>Interactive Area</h1>
<p>The trail will only trigger when hovering inside this container.</p>
<button>Hover Me</button>
</div>
<ez-mouse-trail
style="grid-area: 1 / 1; pointer-events: none; z-index: 2;"
icon-string="flare"
modifier-string="vortex/50s50"
>
</ez-mouse-trail>
</div>
Tip: You don’t need to add pointer-events: none on the trail component as we do it automatically however you can add other pointer-events to override this behaviour.
While Grid is the most modern and clean approach for stacking, there are several other ways to achieve the parent-listening effect depending on your project’s CSS architecture.
Here are the common alternatives to the Grid stack:
1. Absolute Positioning (The Classic Way)
This is the most common method if your container already has a defined height or is part of a legacy layout.
<div style="position: relative; width: 100%; height: 300px; overflow: hidden;">
<div class="content">
<h2>Relative Container</h2>
<p>The trail fills the absolute space of this parent.</p>
</div>
<ez-mouse-trail
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;"
...props
>
</ez-mouse-trail>
</div>
2. Flexbox Stack (Centering focus)
Flexbox isn’t naturally built for stacking on the Z-axis, but you can use it to center content while an absolute trail sits behind or in front.
<div
style="display: flex; align-items: center; justify-content: center; position: relative; height: 300px;"
>
<div style="z-index: 1;">
<button>Interactive Button</button>
</div>
<ez-mouse-trail style="position: absolute; inset: 0; pointer-events: none;">
</ez-mouse-trail>
</div>
3. Inset / Margin Hack
If you don’t want to use width: 100%, you can use the inset: 0 shorthand on an absolute component to force it to match the parent’s dimensions exactly. Altough this is somewhat inconsistent
<div style="position: relative; padding: 50px; border: 2px dashed #444;">
<p>Text content that dictates the parent's size.</p>
<ez-mouse-trail style="position: absolute; inset: 0;"></ez-mouse-trail>
</div>
Implementation Note: Why the parent matters
The component attaches listeners for mousemove, mousedown, and mouseup directly to the parentElement.
Scoped Interaction: The particles only spawn when the mouse is within that specific box.
Clean Cleanup: If the parent is removed from the DOM, the listeners are garbage collected automatically.
Z-Index Tip: Always ensure your ez-mouse-trail has a higher z-index than your background but pointer-events: none so it doesn’t block clicks to your UI elements.
Properties
The attributes are used inside the html tag in the following way:
<ez-mouse-trail property-name="property_value"> </ez-mouse-trail>
Types are there just for clarification, web-components by default only accept
string, so you wouldn’t pass property=10 but property="10"
Core Configuration
max-items
- Type:
number - Default:
20 - Description: Limits the pool of active particles. Once this limit is reached, no new particles will spawn until older ones die. High values (100+) may impact performance.
life-single
- Type:
number(milliseconds) - Default:
1000 - Description: The duration a particle exists from spawn to death. Modifiers can interact with this value to create fading or scaling effects over time.
trail-behaviour
- Type:
TrailBehaviour - Default:
"hover" - Valid Values:
click: Spawns particles only at the exact moment and location of a mouse click.hover: Spawns particles following the mouse cursor while it is inside the container.drag: Particles only spawn if the mouse button is held down while moving.click_and_hover: Spawns on hover, but creates a persistent “fountain” at click locations.move: Similar to hover, but strictly requires the mouse to be in motion to spawn.area: Ignores mouse position; randomly spawns particles anywhere within the component bounds.
Spawning Logic
spawn-behavior
- Type:
SpawnBehavior - Default:
"chance" - Valid Values:
timer: Spawns particles at a fixed interval.chance: Spawns based on a percentage roll calculated every frame.
spawn-variable
- Type:
number - Default:
20 - Description: - If
spawn_behavioristimer: This represents particles per second.- If
spawn_behaviorischance: This is the % probability (0-100) per frame.
- If
click-duration
- Type:
number(milliseconds) - Default:
1000 - Description: Specific to the
click_and_hoverbehavior; determines how long a clicked coordinate remains an active spawn point for new particles.
Modifier System
modifier-string
- Type:
string - Default:
"" - Description: A comma-separated list of behaviors.
- Format:
name/main/secondary - Available Values: name is a string, either main or secondary can be positive, negative, or zero. For more information go to the modifier part in this page
- Example:
launch/10/45,friction/-10,bounds-bounce/100/5 - Note:
main(usually -100 to 100) andsecondary(usually 0 to 100) are parameters passed to the internal math functions of the modifier.
Visuals & Colors
icon-string
- Type:
string - Default:
"" - Description: A comma-separated list of [Material Icon](https:
fonts.google.com/icons) names (e.g.,
heart,star,bolt). If the string is not a valid icon name, the component will render the literal text/unicode. Instead of spaces (Ex: chevron right) the names use underscores (Ex:chevron_right)
icon-order
- Type:
IconOrder - Default:
"random" - Valid Values:
random,sequence(follows the order inicon_string).
color-string
- Type:
string - Default:
"" - Description: A comma-separated list of hex colors. The component cycles
through these when spawning particles. Supports standard hex or hex with alpha
(e.g.,
#FF000088).
default-color
- Type:
string(Hex) - Default:
"#ffffff" - Description: The fallback color used if
color_stringis empty.
icon-size
- Type:
number(pixels) - Default:
20 - Description: The base CSS pixel size for the rendered icons.
icon-resolution
- Type:
number - Default:
1.5 - Description: Internal canvas scaling for the icons. Higher values provide crisper icons but require more memory.
Typography (Material Symbols Styling)
font-style
- Type:
FontStyle - Default:
"Rounded" - Valid Values:
Outlined,Rounded,Sharp.
font-type
- Type:
FontType - Default:
"fill" - Valid Values:
fill(solid),nofill(outline).
font-optical-size
- Type:
number - Default:
24 - Valid Values:
20,24,40,48.
font-weight
- Type:
number - Default:
400 - Range:
100to900.
font-grade
- Type:
number - Default:
0 - Range: Typically
-25to200. Adjusts the thickness of the icon strokes.
Modifiers
Modifiers are applied via the modifier_string prop. Format:
modifier_name/main_value/secondary_value Example:
launch/15/90,friction/5,gravity/10/-180
Directional modifiers:
launch
- Usage:
launch/speed/direction_degrees - Logic: A “One-Shot” modifier that gives an initial burst of speed.
- Params:
mainis speed (default 10),secondaryis angle in degrees (default 0).
friction
- Usage:
friction/amount - Logic: Gradually slows down velocity. Essential for “launch” or “influence” to feel natural.
- Params:
mainis percentage of slowing (default 5).
gravity
- Usage:
gravity/strength/angle - Logic: Constant pull in a specific direction.
- Params:
mainis acceleration strength,secondaryis direction in degrees (90 is down).
drunken
- Usage:
drunken/speed/factor - Logic: Adds Brownian-like erratic motion to particles.
- Params:
mainis speed of movement,secondaryis the frequency of direction changes.
jitter
- Usage:
jitter/intensity - Logic: Adds random micro-vibrations to the particle position every frame.
Mouse Interaction
influence
- Usage:
influence/force/radius - Logic: Attracts or repels particles near the mouse.
- Params:
mainis force (positive to repel, negative to attract),secondaryis effect radius.
vortex
- Usage:
vortex/area/speed - Logic: Particles orbit the mouse cursor while being pulled inward.
orbit
- Usage:
orbit/speed/dead_zone - Logic: Simulates planetary gravity toward the mouse cursor.
sticky_trail
- Usage:
sticky_trail/speed/clear_zone - Logic: Particles get “sucked” into the wake of the mouse as it moves.
Life & State Management
alive_always:
Keeps particles at 100% life indefinitely.
alive_mouseover:
Keeps particles alive only while the mouse is inside the component.
alive_mousedown:
Keeps particles alive only while the mouse button is held.
alive_mousemove:
Keeps particles alive only while the mouse is actively moving.
Chain & Follow Behaviors
chain
- Usage:
chain/speed/friction - Logic: Particles follow each other in a literal chain. Index 0 follows the mouse.
chain_rotate:
Children in a chain point toward their “parent” particle, can be used without chain modifier.
chain_scale:
Gradually shrinks particles based on their index in the chain, can be used without chain modifier.
chain_fade:
Gradually fades particles based on their index in the chain, can be used without chain modifier.
Oscillation & Shape
wave_h / wave_v
- Usage:
wave_h/intensity/frequency - Logic: Sine-wave oscillation on the Horizontal (h) or Vertical (v) axis.
spiral
- Usage:
spiral/speed/range - Logic: Forces particles into a mathematical spiral path from their origin point.
pulse
- Usage:
pulse/intensity/frequency - Logic: Rhythmic scaling (growing and shrinking).
flow_field
- Usage:
flow_field/scale/strength - Logic: Moves particles based on a coordinate-based trig field (simulates wind/water).
Boundaries
bounds_bounce
- Usage:
bounds_bounce/bounciness/padding - Logic: Particles bounce off the edges of the component.
mainis elasticity (0-100).
bounds_wrap
- Usage:
bounds_wrap/padding - Logic: Particles that leave one side reappear on the opposite side.
Initial State (One-Shot)
These modifiers only run once when the particle is first created.
init_offset:
init_offset/x/y - Starts the particle at a fixed offset.
init_random:
init_random/xRange/yRange - Starts the particle within a random area.
init_rotation:
init_rotation/angle - Sets starting rotation.
init_rotation_random:
init_rotation_random/range - Sets a random starting rotation.
init_velocity_random:
init_velocity_random/min_deg/max_deg - Randomizes the direction of existing
velocity.
init_scale:
init_scale/value - Sets starting size.
init_scale_random:
init_scale_random/low/high - Sets a random starting size.
Visual Effects
hue_cycle
- Usage:
hue_cycle/speed/saturation_adj - Logic: Cycles the particle color through the HSL spectrum over its lifetime.
rotate
- Usage:
rotate/speed/randomness - Logic: Continuous rotation.
secondarydetermines the chance (0-100) of spinning counter-clockwise.
size_drift
- Usage:
size_drift/speed - Logic: Scales up or down the particle, don’t use with any alive modifiers as it might grow/shrink forever