StringCursor Module
Translate pointer motion into CSS-driven hover states. StringCursor observes desktop mouse movement, writes normalized coordinates to targets, and keeps a custom cursor element in sync with eased values.
Activation primer: Add
string="cursor"to every element you wantStringCursorto control. Supplystring-id="your-id"when you need a stable handle for events, mirrors, orstring-copy-from; otherwise StringTune generates one automatically.
HTML Attributes
| Attribute | Type | Default | Controls | Practical notes |
|---|---|---|---|---|
string-target-disable | boolean | false | Opt the element out of cursor interactions even when flagged with string="cursor" | Use on wrappers that should not respond despite inheriting the attribute |
string-target-style-disable | boolean | false | Skip writing --x/--y CSS variables | Ideal when you consume only the emitted events |
string-cursor-class | string | "" | Class added to the global [string-cursor] element while the target is hovered | Useful for theme-aware pointer styling |
string-alignment | enum (start/center/end) | center | How the module normalizes pointer position across the element | center yields -1…1, start/end map to 0…1 ranges |
string-lerp | number | 0.2 | Lerp factor applied to cursor easing (remapped internally to 0.05–0.65) | Larger numbers feel tighter; tweak per element for variety |
Global pointer element: add
[string-cursor]to the DOM once (optionally alongside[string-cursor-content]). The module automatically feeds it CSS variables--x,--y,--x-lerp, and--y-lerpin pixels.
Module Snapshot
- Activation attribute:
string="cursor" - Per-target CSS variables:
--x,--y(normalized coordinates) - Global cursor variables:
--x,--y,--x-lerp,--y-lerp(pixels) - Event channels:
cursor:start|move|pixel|end:<id>, plus the globalcursor - Pointer gating: module auto-disables on coarse pointers (touch/pen)
- Lifecycle helpers: attaches MutationObservers + navigation fallbacks to ensure cleanup on SPAs
Basic Usage
import StringTune, { StringCursor } from '@fiddle-digital/string-tune';
const stringTune = StringTune.getInstance();
stringTune.use(StringCursor);
stringTune.start(60);
<div string-cursor class="custom-cursor"></div>
<button string="cursor" string-cursor-class="-hovering" string-lerp="0.35" class="cta">Hover me</button>
.cta {
--tx: calc(var(--x, 0) * 12px);
--ty: calc(var(--y, 0) * 12px);
transform: translate(var(--tx), var(--ty));
transition: box-shadow 0.2s ease;
}
.custom-cursor {
position: fixed;
inset: 0 auto auto 0;
width: 18px;
height: 18px;
margin: -9px 0 0 -9px;
pointer-events: none;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6);
transform: translate3d(var(--x, 0) * 1px, var(--y, 0) * 1px, 0);
}
How It Works
- Hover capture: elements with
string="cursor"register mouseenter/leave listeners when they enter the viewport; Safari navigation quirks are handled internally. - Center sampling: the module tracks half-width/half-height via
CenterCache, allowing coordinates to be normalized even as layouts shift. - Smoothing:
string-lerppasses through an adaptive curve so small numbers still feel fluid; the state sleeps automatically when movement settles below an epsilon. - CSS writes: unless disabled, every frame updates
--x/--y(normalized) on the element and all mirrors created withstring-copy-from. - Global cursor: if
[string-cursor]exists, it receives eased pixel coordinates plus lerp deltas for additional styling control.
Event Signals
| Channel pattern | Payload | Fired when | Common uses |
|---|---|---|---|
cursor:start:<id> | null | Pointer begins moving over the element | Kick off sound cues, toggle hover classes |
cursor:move:<id> | { x: number; y: number; } (normalized) | Normalized coordinates change beyond epsilon | Drive DOM transforms, shaders, or analytics samples |
cursor:pixel:<id> | { x: number; y: number; } (pixels relative to element) | Smoothed pixel offsets update | Position tooltips, magnetic highlights |
cursor:end:<id> | null | Pointer stops moving or leaves the element | Fade out hover embellishments |
cursor | { x: number; y: number; stepX: number; stepY: number; } | Global cursor state changes | Sync the custom pointer, broadcast to a state store |
stringTune.on('cursor:move:cta', ({ x, y }) => {
// x & y are normalized; feed into WebGL uniforms or CSS vars
});
stringTune.on('cursor', ({ x, y }) => {
// global pixel coordinates relative to the viewport origin
});
StringCursor keeps hover choreography responsive—dial the lerp per component, wire events into motion systems, and let the shared cursor element carry the brand’s personality.