A navbar that smoothly collapses as the user scrolls down the page
Preview Animation Live<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script><script>
document.addEventListener("DOMContentLoaded", function () {
gsap.registerPlugin(ScrollTrigger);
function initNavAnimation() {
// Only desktop (change px if needed)
if (window.matchMedia("(min-width: 992px)").matches) {
const navTl = gsap.timeline({
scrollTrigger: {
trigger: "body",
start: "top+=100 top",
toggleActions: "play none none reverse",
}
});
// .navi_wrapper
navTl.fromTo(
".navi_wrapper",
{ width: "100%" },
{ width: "auto", duration: 1, ease: "power4.out" },
0
);
// .navi-logo-animate
navTl.fromTo(
".navi-logo-animate",
{ width: "100%" },
{ width: "0%", duration: 0.5, ease: "power4.out" },
0
);
// .navi-text-hold
navTl.fromTo(
".navi-text-hold",
{ width: "100%" },
{ width: 0, duration: 0.5, ease: "power4.out" },
0
);
}
}
// Run animation on initial load
initNavAnimation();
// Refresh ScrollTrigger & check breakpoint on resize
window.addEventListener("resize", () => {
ScrollTrigger.refresh();
});
});
</script>
Target
Use [data-3d-hover-target] to register any element for 3D tilt tracking based on the global pointer position.
Max Rotate
Use [data-max-rotate] to fine-tune the maximum rotation per element without affecting other [data-3d-hover-target] elements. If you don't add this attribute, it will default to a maximum rotation of 20 degrees.
Perspective
Use transform: perspective(...) on [data-3d-hover-target] to make the element tilt in true 3D space. The regular perspective property only affects children, not the element itself. Since this is defined in CSS, you could have different perspective values for different targets.
Inner Layers
Use [data-3d-hover-inner="layer-x"] inside a [data-3d-hover-target] to add separate depth planes that move naturally as the parent tilts. You can define as many layers as you like, each with its own translateZ() value to control how far it sits in 3D space. Larger translateZ values make the layer appear closer to the viewer, creating a stronger parallax effect.
Pointer Devices Only
The script auto-disables on non-hover devices using (hover: hover) and (pointer: fine) so [data-3d-hover-target] won't attach listeners on touch-only screens.
Reduced Motion
When the user prefers reduced motion, the script respects prefers-reduced-motion: reduce and does not run.
Be the first to get notified of new components we release every week