Pointer Parallax Layers
A copy-paste cursors component in pure HTML, CSS & vanilla JS. Zero dependencies, framework-agnostic, MIT-licensed.
CursorsHTMLJavaScriptCSSany framework
Parallax
Copy into your project
HTML
<div class="nuda-cur2-parallax-layers">
<span class="nuda-cur2-parallax-layers__layer nuda-cur2-parallax-layers__layer--back" aria-hidden="true"></span>
<span class="nuda-cur2-parallax-layers__layer nuda-cur2-parallax-layers__layer--mid" aria-hidden="true"></span>
<span class="nuda-cur2-parallax-layers__layer nuda-cur2-parallax-layers__layer--front">Parallax</span>
</div>JavaScript
/* Pointer Parallax Layers — each layer shifts by its own --depth,
multiplied by the pointer's normalized position (-0.5..0.5). */
(function () {
document.querySelectorAll('.nuda-cur2-parallax-layers').forEach(function (area) {
area.addEventListener('mousemove', function (e) {
var rect = area.getBoundingClientRect();
var px = (e.clientX - rect.left) / rect.width - 0.5;
var py = (e.clientY - rect.top) / rect.height - 0.5;
area.style.setProperty('--px', px.toFixed(3));
area.style.setProperty('--py', py.toFixed(3));
});
area.addEventListener('mouseleave', function () {
area.style.setProperty('--px', '0');
area.style.setProperty('--py', '0');
});
});
})();CSS
.nuda-cur2-parallax-layers {
--px: 0;
--py: 0;
position: relative;
width: 100%;
max-width: 220px;
height: 120px;
margin: 0 auto;
border-radius: 12px;
overflow: hidden;
background: radial-gradient(120% 100% at 50% 0%,#1a1a1a,#0a0a0a);
border: 1px solid rgba(255,255,255,.08);
}
.nuda-cur2-parallax-layers__layer {
position: absolute;
top: 50%;
left: 50%;
transition: transform .18s ease-out;
will-change: transform;
pointer-events: none;
}
.nuda-cur2-parallax-layers__layer--back {
--depth: 10px;
width: 90px;
height: 90px;
border-radius: 50%;
background: radial-gradient(circle,rgba(228,255,84,.18),transparent 70%);
transform: translate(-50%,-50%) translate(calc(var(--px) * var(--depth)),calc(var(--py) * var(--depth)));
}
.nuda-cur2-parallax-layers__layer--mid {
--depth: 22px;
width: 46px;
height: 46px;
border-radius: 50%;
border: 1px solid rgba(228,255,84,.4);
transform: translate(-50%,-50%) translate(calc(var(--px) * var(--depth)),calc(var(--py) * var(--depth)));
}
.nuda-cur2-parallax-layers__layer--front {
--depth: 40px;
padding: 5px 12px;
border-radius: 999px;
background: #e4ff54;
color: #0a0a0a;
font-size: 11px;
font-weight: 700;
white-space: nowrap;
transform: translate(-50%,-50%) translate(calc(var(--px) * var(--depth)),calc(var(--py) * var(--depth)));
}
@media (prefers-reduced-motion:reduce) {
.nuda-cur2-parallax-layers__layer {
transition: none;
transform: translate(-50%,-50%)!important;
}
}
How to use Pointer Parallax Layers
Paste the HTML where you need it and the CSS into a global stylesheet (or a <style> tag). Every class is prefixed nuda- so it never collides with Tailwind or your own styles. Tweak the CSS custom properties to match your design system.
Works in React, Vue, Svelte, Astro, Next.js, Nuxt, Laravel Blade, Django, Rails — or a single .html file. No npm install, no build step.