Pointer Tilt
3D & Depth · Static · pure CSS
A rigid, glossy slab that tilts in real 3D toward your cursor: rotateX and rotateY are derived live from the pointer under a perspective, while a diagonal specular sheen slides across the letters tracking the horizontal cursor position. A floating counter-shadow swings opposite the tilt, so the headline reads as a card hovering off the page.
How it works
Pointer Tilt is a static 3d & depth text effect rendered entirely in CSS. It reacts to the pointer through CSS custom properties updated by a tiny inline script.
Controls
Pointer Tilt exposes 4 dedicated controls — Hue, Max Tilt, Sheen and Shadow Depth — 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
/* Pointer Tilt — made with TEXT-FX · https://text-fx.app
* HTML: needs the small pointer-move JS snippet.
* Font: 'Anton', sans-serif (load from Google Fonts).
*/
.text-effect {
font-family: 'Anton', sans-serif;
font-weight: 400;
letter-spacing: 2px;
text-transform: none;
}
.text-effect {
--mx: 42%;
--my: 38%;
display: inline-block;
transform-style: preserve-3d;
transform: perspective(700px) rotateX(clamp(-11deg, calc((var(--my) - 50%) / 1% * 0.22deg), 11deg)) rotateY(clamp(-11deg, calc((var(--mx) - 50%) / 1% * -0.22deg), 11deg));
background: linear-gradient(115deg, transparent 35%, hsl(0 0% 100% / 0.446) 50%, transparent 65%), linear-gradient(180deg, hsl(228 45% 84%), hsl(228 58% 52%));
background-size: 250% 100%, 100% 100%;
background-position: var(--mx) 0, 0 0;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
filter: drop-shadow(calc((50% - var(--mx)) / 1% * 0.1167px) calc(4px + (50% - var(--my)) / 1% * 0.0875px) 13px hsl(228 70% 56% / 0.4));
transition: transform 0.12s ease-out, filter 0.12s ease-out, background-position 0.12s ease-out;
will-change: transform, filter, background-position;
}
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: 'Anton', sans-serif;
font-weight: 400;
letter-spacing: 2px;
text-transform: none;
}
.text-effect {
--mx: 42%;
--my: 38%;
display: inline-block;
transform-style: preserve-3d;
transform: perspective(700px) rotateX(clamp(-11deg, calc((var(--my) - 50%) / 1% * 0.22deg), 11deg)) rotateY(clamp(-11deg, calc((var(--mx) - 50%) / 1% * -0.22deg), 11deg));
background: linear-gradient(115deg, transparent 35%, hsl(0 0% 100% / 0.446) 50%, transparent 65%), linear-gradient(180deg, hsl(228 45% 84%), hsl(228 58% 52%));
background-size: 250% 100%, 100% 100%;
background-position: var(--mx) 0, 0 0;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
filter: drop-shadow(calc((50% - var(--mx)) / 1% * 0.1167px) calc(4px + (50% - var(--my)) / 1% * 0.0875px) 13px hsl(228 70% 56% / 0.4));
transition: transform 0.12s ease-out, filter 0.12s ease-out, background-position 0.12s ease-out;
will-change: transform, filter, background-position;
}
</style>
<div class="text-effect">Your text</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
- 3D & Depth
- Type
- Static
- Browser support
- Tilts in real 3D toward the cursor via pointer-driven rotateX/rotateY; the static preview shows a resting lean.
- Capabilities
- pure, pointer