Cursor Repel
Interactive & Advanced · Animated · pure CSS
Each letter measures its own distance from the cursor and slides, lifts and leans away, so the whole word fans open around the pointer while the nearest letters bloom in colour. A purely spatial, pointer-tracked repel built entirely from per-letter calc against live custom properties — no JS animation, just transitions that glide.
How it works
Cursor Repel is an animated interactive & advanced text effect rendered entirely in CSS. Each character is wrapped in its own span so it can animate independently — the HTML and JSX exports include that per-letter markup. It reacts to the pointer through CSS custom properties updated by a tiny inline script.
Controls
Cursor Repel exposes 4 dedicated controls — Repel, Falloff, Lift and Tilt — on top of the shared type controls (font, weight, letter-spacing and case). Open it in the generator to tune every value live, then copy the updated CSS.
CSS
/* Cursor Repel — made with TEXT-FX · https://text-fx.app
* HTML: each character is wrapped in a <span> — see the HTML export; needs the small pointer-move JS snippet.
* Font: 'Bricolage Grotesque', sans-serif (load from Google Fonts).
*/
.text-effect {
font-family: 'Bricolage Grotesque', sans-serif;
font-weight: 400;
letter-spacing: 0px;
text-transform: none;
}
.text-effect {
--mx: 50%;
--my: 50%;
white-space: pre;
color: hsl(228 14% 88%);
cursor: crosshair;
}
.text-effect .fx-ch {
display: inline-block;
--pos: calc((var(--i) + 0.5) / var(--n) * 100%);
--dx: calc(var(--pos) - var(--mx));
--adx: max(var(--dx), calc(-1 * var(--dx)));
--near: max(0%, calc(44% - var(--adx)));
translate: clamp(-62%, calc(var(--dx) * 0.47), 62%) calc(var(--near) * -0.75);
rotate: calc(clamp(-1, var(--dx) / 50%, 1) * 13deg);
color: hsl(228 14% 88%);
color: color-mix(in oklab, hsl(228 14% 88%), hsl(288 90% 74%) clamp(0%, calc(var(--near) * 2.045), 100%));
transition: translate 0.5s cubic-bezier(0.22, 1, 0.36, 1),
rotate 0.5s cubic-bezier(0.22, 1, 0.36, 1), color 0.4s ease;
will-change: translate, rotate;
}
HTML
This effect needs the markup below (per-letter spans, SVG defs, or a data-text attribute).
<!-- Made with TEXT-FX · https://text-fx.app -->
<style>
.text-effect {
font-family: 'Bricolage Grotesque', sans-serif;
font-weight: 400;
letter-spacing: 0px;
text-transform: none;
}
.text-effect {
--mx: 50%;
--my: 50%;
white-space: pre;
color: hsl(228 14% 88%);
cursor: crosshair;
}
.text-effect .fx-ch {
display: inline-block;
--pos: calc((var(--i) + 0.5) / var(--n) * 100%);
--dx: calc(var(--pos) - var(--mx));
--adx: max(var(--dx), calc(-1 * var(--dx)));
--near: max(0%, calc(44% - var(--adx)));
translate: clamp(-62%, calc(var(--dx) * 0.47), 62%) calc(var(--near) * -0.75);
rotate: calc(clamp(-1, var(--dx) / 50%, 1) * 13deg);
color: hsl(228 14% 88%);
color: color-mix(in oklab, hsl(228 14% 88%), hsl(288 90% 74%) clamp(0%, calc(var(--near) * 2.045), 100%));
transition: translate 0.5s cubic-bezier(0.22, 1, 0.36, 1),
rotate 0.5s cubic-bezier(0.22, 1, 0.36, 1), color 0.4s ease;
will-change: translate, rotate;
}
</style>
<div class="text-effect"><span class="fx-ch" style="--i:0;--n:9;--rev:8;--mid:4">Y</span><span class="fx-ch" style="--i:1;--n:9;--rev:7;--mid:4">o</span><span class="fx-ch" style="--i:2;--n:9;--rev:6;--mid:4">u</span><span class="fx-ch" style="--i:3;--n:9;--rev:5;--mid:4">r</span><span class="fx-ch" style="--i:4;--n:9;--rev:4;--mid:4"> </span><span class="fx-ch" style="--i:5;--n:9;--rev:3;--mid:4">t</span><span class="fx-ch" style="--i:6;--n:9;--rev:2;--mid:4">e</span><span class="fx-ch" style="--i:7;--n:9;--rev:1;--mid:4">x</span><span class="fx-ch" style="--i:8;--n:9;--rev:0;--mid:4">t</span></div>
<script>
const fx = document.querySelector('.text-effect');
if (fx) {
fx.addEventListener('pointermove', (e) => {
const r = fx.getBoundingClientRect();
if (!r.width || !r.height) return;
fx.style.setProperty('--mx', ((e.clientX - r.left) / r.width) * 100 + '%');
fx.style.setProperty('--my', ((e.clientY - r.top) / r.height) * 100 + '%');
});
fx.addEventListener('pointerleave', () => {
fx.style.removeProperty('--mx');
fx.style.removeProperty('--my');
});
}
</script>
- Category
- Interactive & Advanced
- Type
- Animated
- Browser support
- Letters scatter from the cursor via pointer-tracked per-letter transforms — the static preview shows the resting centre bloom.
- Capabilities
- perLetter, pointer