
Documentation
Webflow
Code
Setup: External Scripts
External Scripts in Webflow
Make sure to always put the External Scripts before the Javascript step of the resource.
In this video you learn where to put these in your Webflow project? Or how to include a paid GSAP Club plugin in your project?
HTML
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/InertiaPlugin.min.js"></script>
Step 1: Copy structure to Webflow
Copy structure to Webflow
In the video below we described how you can copy + paste the structure of this resource to your Webflow project.
Copy to Webflow
Webflow structure is not required for this resource.
Step 1: Add HTML
HTML
<section data-momentum-hover-init="" class="section-resource">
<div class="section-resource__collection">
<div class="section-resource__list">
<!-- Card 1 -->
<div class="section-resource__item">
<div data-momentum-hover-element="" class="demo-card__wrap">
<div data-momentum-hover-target="" class="demo-card">
<div class="demo-card__before"></div>
<img src="https://cdn.prod.website-files.com/684d7179e99d2a34dfe75d9f/686b8c064494dac669a1b7ed_portrait-1.jpg" loading="eager" alt="Jess, Co-Founder" class="demo-card__image">
<div class="demo-card__content">
<div class="demo-card__name">
<h3 class="demo-card__h3">Jess</h3>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="demo-card__check-svg"><path d="M13.06 3.06005L14.56 4.56005C14.8411 4.84143 15.2224 4.9997 15.62 5.00005H17.5C17.8979 5.00005 18.2794 5.15808 18.5607 5.43939C18.842 5.72069 19 6.10222 19 6.50005V8.38005C19.0004 8.77774 19.1587 9.15901 19.44 9.44005L20.94 10.94C21.0803 11.0786 21.1917 11.2437 21.2677 11.4257C21.3438 11.6076 21.3829 11.8028 21.3829 12C21.3829 12.1972 21.3438 12.3925 21.2677 12.5744C21.1917 12.7564 21.0803 12.9215 20.94 13.06L19.44 14.56C19.1587 14.8411 19.0004 15.2224 19 15.62V17.5C19 17.8979 18.842 18.2794 18.5607 18.5607C18.2794 18.842 17.8979 19 17.5 19H15.62C15.2224 19.0004 14.8411 19.1587 14.56 19.44L13.06 20.94C12.9215 21.0803 12.7564 21.1917 12.5744 21.2677C12.3925 21.3438 12.1972 21.3829 12 21.3829C11.8028 21.3829 11.6076 21.3438 11.4257 21.2677C11.2437 21.1917 11.0786 21.0803 10.94 20.94L9.44005 19.44C9.15901 19.1587 8.77774 19.0004 8.38005 19H6.50005C6.10222 19 5.72069 18.842 5.43939 18.5607C5.15808 18.2794 5.00005 17.8979 5.00005 17.5V15.62C4.9997 15.2224 4.84143 14.8411 4.56005 14.56L3.06005 13.06C2.91976 12.9215 2.80837 12.7564 2.73235 12.5744C2.65633 12.3925 2.61719 12.1972 2.61719 12C2.61719 11.8028 2.65633 11.6076 2.73235 11.4257C2.80837 11.2437 2.91976 11.0786 3.06005 10.94L4.56005 9.44005C4.84143 9.15901 4.9997 8.77774 5.00005 8.38005V6.50005C5.00005 6.10222 5.15808 5.72069 5.43939 5.43939C5.72069 5.15808 6.10222 5.00005 6.50005 5.00005H8.38005C8.77774 4.9997 9.15901 4.84143 9.44005 4.56005L10.94 3.06005C11.0786 2.91976 11.2437 2.80837 11.4257 2.73235C11.6076 2.65633 11.8028 2.61719 12 2.61719C12.1972 2.61719 12.3925 2.65633 12.5744 2.73235C12.7564 2.80837 12.9215 2.91976 13.06 3.06005Z" fill="#D3FF5B"></path><path d="M8.5 11.5L11 14L15 10" stroke="black" stroke-width="1.5" stroke-miterlimit="10"></path></svg>
</div>
<p class="demo-card__job-title-p">Co-Founder</p>
</div>
</div>
</div>
</div>
<!-- Card 1 -->
<div class="section-resource__item">
<div data-momentum-hover-element="" class="demo-card__wrap">
<div data-momentum-hover-target="" class="demo-card">
<div class="demo-card__before"></div>
<img src="https://cdn.prod.website-files.com/684d7179e99d2a34dfe75d9f/686b8c06662f765388fa0e57_portrait-2.jpg" loading="eager" alt="Edward, Finance" class="demo-card__image">
<div class="demo-card__content">
<div class="demo-card__name">
<h3 class="demo-card__h3">Edward</h3>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="demo-card__check-svg"><path d="M13.06 3.06005L14.56 4.56005C14.8411 4.84143 15.2224 4.9997 15.62 5.00005H17.5C17.8979 5.00005 18.2794 5.15808 18.5607 5.43939C18.842 5.72069 19 6.10222 19 6.50005V8.38005C19.0004 8.77774 19.1587 9.15901 19.44 9.44005L20.94 10.94C21.0803 11.0786 21.1917 11.2437 21.2677 11.4257C21.3438 11.6076 21.3829 11.8028 21.3829 12C21.3829 12.1972 21.3438 12.3925 21.2677 12.5744C21.1917 12.7564 21.0803 12.9215 20.94 13.06L19.44 14.56C19.1587 14.8411 19.0004 15.2224 19 15.62V17.5C19 17.8979 18.842 18.2794 18.5607 18.5607C18.2794 18.842 17.8979 19 17.5 19H15.62C15.2224 19.0004 14.8411 19.1587 14.56 19.44L13.06 20.94C12.9215 21.0803 12.7564 21.1917 12.5744 21.2677C12.3925 21.3438 12.1972 21.3829 12 21.3829C11.8028 21.3829 11.6076 21.3438 11.4257 21.2677C11.2437 21.1917 11.0786 21.0803 10.94 20.94L9.44005 19.44C9.15901 19.1587 8.77774 19.0004 8.38005 19H6.50005C6.10222 19 5.72069 18.842 5.43939 18.5607C5.15808 18.2794 5.00005 17.8979 5.00005 17.5V15.62C4.9997 15.2224 4.84143 14.8411 4.56005 14.56L3.06005 13.06C2.91976 12.9215 2.80837 12.7564 2.73235 12.5744C2.65633 12.3925 2.61719 12.1972 2.61719 12C2.61719 11.8028 2.65633 11.6076 2.73235 11.4257C2.80837 11.2437 2.91976 11.0786 3.06005 10.94L4.56005 9.44005C4.84143 9.15901 4.9997 8.77774 5.00005 8.38005V6.50005C5.00005 6.10222 5.15808 5.72069 5.43939 5.43939C5.72069 5.15808 6.10222 5.00005 6.50005 5.00005H8.38005C8.77774 4.9997 9.15901 4.84143 9.44005 4.56005L10.94 3.06005C11.0786 2.91976 11.2437 2.80837 11.4257 2.73235C11.6076 2.65633 11.8028 2.61719 12 2.61719C12.1972 2.61719 12.3925 2.65633 12.5744 2.73235C12.7564 2.80837 12.9215 2.91976 13.06 3.06005Z" fill="#D3FF5B"></path><path d="M8.5 11.5L11 14L15 10" stroke="black" stroke-width="1.5" stroke-miterlimit="10"></path></svg>
</div>
<p class="demo-card__job-title-p">Finance</p>
</div>
</div>
</div>
</div>
<!-- Card 3 -->
<div class="section-resource__item">
<div data-momentum-hover-element="" class="demo-card__wrap">
<div data-momentum-hover-target="" class="demo-card">
<div class="demo-card__before"></div>
<img src="https://cdn.prod.website-files.com/684d7179e99d2a34dfe75d9f/686b8c074f2f56abd265e05a_portrait-3.jpg" loading="eager" alt="Mel, Product Designer" class="demo-card__image">
<div class="demo-card__content">
<div class="demo-card__name">
<h3 class="demo-card__h3">Mel</h3>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="demo-card__check-svg"><path d="M13.06 3.06005L14.56 4.56005C14.8411 4.84143 15.2224 4.9997 15.62 5.00005H17.5C17.8979 5.00005 18.2794 5.15808 18.5607 5.43939C18.842 5.72069 19 6.10222 19 6.50005V8.38005C19.0004 8.77774 19.1587 9.15901 19.44 9.44005L20.94 10.94C21.0803 11.0786 21.1917 11.2437 21.2677 11.4257C21.3438 11.6076 21.3829 11.8028 21.3829 12C21.3829 12.1972 21.3438 12.3925 21.2677 12.5744C21.1917 12.7564 21.0803 12.9215 20.94 13.06L19.44 14.56C19.1587 14.8411 19.0004 15.2224 19 15.62V17.5C19 17.8979 18.842 18.2794 18.5607 18.5607C18.2794 18.842 17.8979 19 17.5 19H15.62C15.2224 19.0004 14.8411 19.1587 14.56 19.44L13.06 20.94C12.9215 21.0803 12.7564 21.1917 12.5744 21.2677C12.3925 21.3438 12.1972 21.3829 12 21.3829C11.8028 21.3829 11.6076 21.3438 11.4257 21.2677C11.2437 21.1917 11.0786 21.0803 10.94 20.94L9.44005 19.44C9.15901 19.1587 8.77774 19.0004 8.38005 19H6.50005C6.10222 19 5.72069 18.842 5.43939 18.5607C5.15808 18.2794 5.00005 17.8979 5.00005 17.5V15.62C4.9997 15.2224 4.84143 14.8411 4.56005 14.56L3.06005 13.06C2.91976 12.9215 2.80837 12.7564 2.73235 12.5744C2.65633 12.3925 2.61719 12.1972 2.61719 12C2.61719 11.8028 2.65633 11.6076 2.73235 11.4257C2.80837 11.2437 2.91976 11.0786 3.06005 10.94L4.56005 9.44005C4.84143 9.15901 4.9997 8.77774 5.00005 8.38005V6.50005C5.00005 6.10222 5.15808 5.72069 5.43939 5.43939C5.72069 5.15808 6.10222 5.00005 6.50005 5.00005H8.38005C8.77774 4.9997 9.15901 4.84143 9.44005 4.56005L10.94 3.06005C11.0786 2.91976 11.2437 2.80837 11.4257 2.73235C11.6076 2.65633 11.8028 2.61719 12 2.61719C12.1972 2.61719 12.3925 2.65633 12.5744 2.73235C12.7564 2.80837 12.9215 2.91976 13.06 3.06005Z" fill="#D3FF5B"></path><path d="M8.5 11.5L11 14L15 10" stroke="black" stroke-width="1.5" stroke-miterlimit="10"></path></svg>
</div>
<p class="demo-card__job-title-p">Product Designer</p>
</div>
</div>
</div>
<div data-momentum-hover-element="" class="demo-badge__wrap">
<div data-momentum-hover-target="" class="demo-badge"><img src="https://cdn.prod.website-files.com/684d7179e99d2a34dfe75d9f/686b8faf73f8f7c44bcab43d_badge.jpg" alt="" class="demo-badge__img"></div>
</div>
</div>
<!-- Card 4 -->
<div class="section-resource__item">
<div data-momentum-hover-element="" class="demo-card__wrap">
<div data-momentum-hover-target="" class="demo-card">
<div class="demo-card__before"></div>
<img src="https://cdn.prod.website-files.com/684d7179e99d2a34dfe75d9f/686b8c0642f1062f8a5ab064_portrait-4.jpg" loading="eager" alt="Steve, Marketing & Support" class="demo-card__image">
<div class="demo-card__content">
<div class="demo-card__name">
<h3 class="demo-card__h3">Steve</h3>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="demo-card__check-svg"><path d="M13.06 3.06005L14.56 4.56005C14.8411 4.84143 15.2224 4.9997 15.62 5.00005H17.5C17.8979 5.00005 18.2794 5.15808 18.5607 5.43939C18.842 5.72069 19 6.10222 19 6.50005V8.38005C19.0004 8.77774 19.1587 9.15901 19.44 9.44005L20.94 10.94C21.0803 11.0786 21.1917 11.2437 21.2677 11.4257C21.3438 11.6076 21.3829 11.8028 21.3829 12C21.3829 12.1972 21.3438 12.3925 21.2677 12.5744C21.1917 12.7564 21.0803 12.9215 20.94 13.06L19.44 14.56C19.1587 14.8411 19.0004 15.2224 19 15.62V17.5C19 17.8979 18.842 18.2794 18.5607 18.5607C18.2794 18.842 17.8979 19 17.5 19H15.62C15.2224 19.0004 14.8411 19.1587 14.56 19.44L13.06 20.94C12.9215 21.0803 12.7564 21.1917 12.5744 21.2677C12.3925 21.3438 12.1972 21.3829 12 21.3829C11.8028 21.3829 11.6076 21.3438 11.4257 21.2677C11.2437 21.1917 11.0786 21.0803 10.94 20.94L9.44005 19.44C9.15901 19.1587 8.77774 19.0004 8.38005 19H6.50005C6.10222 19 5.72069 18.842 5.43939 18.5607C5.15808 18.2794 5.00005 17.8979 5.00005 17.5V15.62C4.9997 15.2224 4.84143 14.8411 4.56005 14.56L3.06005 13.06C2.91976 12.9215 2.80837 12.7564 2.73235 12.5744C2.65633 12.3925 2.61719 12.1972 2.61719 12C2.61719 11.8028 2.65633 11.6076 2.73235 11.4257C2.80837 11.2437 2.91976 11.0786 3.06005 10.94L4.56005 9.44005C4.84143 9.15901 4.9997 8.77774 5.00005 8.38005V6.50005C5.00005 6.10222 5.15808 5.72069 5.43939 5.43939C5.72069 5.15808 6.10222 5.00005 6.50005 5.00005H8.38005C8.77774 4.9997 9.15901 4.84143 9.44005 4.56005L10.94 3.06005C11.0786 2.91976 11.2437 2.80837 11.4257 2.73235C11.6076 2.65633 11.8028 2.61719 12 2.61719C12.1972 2.61719 12.3925 2.65633 12.5744 2.73235C12.7564 2.80837 12.9215 2.91976 13.06 3.06005Z" fill="#D3FF5B"></path><path d="M8.5 11.5L11 14L15 10" stroke="black" stroke-width="1.5" stroke-miterlimit="10"></path></svg>
</div>
<p class="demo-card__job-title-p">Marketing & Support</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
HTML structure is not required for this resource.
Step 2: Add CSS
CSS
.section-resource {
justify-content: center;
align-items: center;
min-height: 100svh;
padding-top: 7.5em;
padding-bottom: 7.5em;
display: flex;
background-color: #393933;
}
.section-resource__collection {
flex: 1;
justify-content: center;
max-width: 80em;
padding-left: 3em;
padding-right: 3em;
}
.section-resource__list {
grid-column-gap: 2em;
grid-row-gap: 2em;
flex-flow: wrap;
height: 100%;
display: flex;
}
.section-resource__item {
width: calc(25% - 0.25px - 1.5em);
position: relative;
}
.demo-card__wrap {
width: 100%;
position: relative;
}
.demo-card {
color: #fff;
border-radius: 1.5em;
width: 100%;
position: relative;
overflow: hidden;
}
.demo-card__before {
pointer-events: none;
padding-top: 150%;
}
.demo-card__image {
object-fit: cover;
width: 100%;
max-width: none;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.demo-card__content {
grid-column-gap: .5em;
grid-row-gap: .5em;
flex-flow: column;
justify-content: flex-end;
width: 100%;
height: 100%;
padding: 2em;
display: flex;
position: absolute;
top: 0;
left: 0;
}
.demo-card__name {
grid-column-gap: .25em;
grid-row-gap: .25em;
justify-content: flex-start;
align-items: center;
display: flex;
}
.demo-card__check-svg {
width: 1.5em;
}
.demo-card__h3 {
margin-top: 0;
margin-bottom: .0625em;
font-size: 1.5em;
font-weight: 500;
line-height: 1;
}
.demo-card__job-title-p {
opacity: .67;
margin-bottom: 0;
font-size: 1em;
font-weight: 400;
line-height: 1;
}
.demo-badge__wrap {
z-index: 5;
border-radius: 50%;
width: 16em;
position: absolute;
top: 25%;
right: 0%;
transform: translate(50%, -50%);
}
.demo-badge {
border-radius: 50%;
width: 50%;
margin: 25%;
position: relative;
overflow: hidden;
}
.demo-badge__img {
width: 100%;
}
@media screen and (max-width: 991px) {
.section-resource__item {
width: calc(50% - 0.5px - 1em);
}
}
@media screen and (max-width: 767px) {
.section-resource__item {
width: 100%;
}
}
Step 2: Add custom Javascript
Custom Javascript in Webflow
In this video, Ilja gives you some guidance about using JavaScript in Webflow:
Step 2: Add Javascript
Step 3: Add Javascript
Javascript
gsap.registerPlugin(InertiaPlugin);
function initMomentumBasedHover() {
// If this device can’t hover with a fine pointer, stop here
if (!window.matchMedia("(hover: hover) and (pointer: fine)").matches) {return;}
// Configuration (tweak these for feel)
const xyMultiplier = 30; // multiplies pointer velocity for x/y movement
const rotationMultiplier = 20; // multiplies normalized torque for rotation speed
const inertiaResistance = 200; // higher = stops sooner
// Pre-build clamp functions for performance
const clampXY = gsap.utils.clamp(-1080, 1080);
const clampRot = gsap.utils.clamp(-60, 60);
// Initialize each root container
document.querySelectorAll('[data-momentum-hover-init]').forEach(root => {
let prevX = 0, prevY = 0;
let velX = 0, velY = 0;
let rafId = null;
// Track pointer velocity (throttled to RAF)
root.addEventListener('mousemove', e => {
if (rafId) return;
rafId = requestAnimationFrame(() => {
velX = e.clientX - prevX;
velY = e.clientY - prevY;
prevX = e.clientX;
prevY = e.clientY;
rafId = null;
});
});
// Attach hover inertia to each child element
root.querySelectorAll('[data-momentum-hover-element]').forEach(el => {
el.addEventListener('mouseenter', e => {
const target = el.querySelector('[data-momentum-hover-target]');
if (!target) return;
// Compute offset from center to pointer
const { left, top, width, height } = target.getBoundingClientRect();
const centerX = left + width / 2;
const centerY = top + height / 2;
const offsetX = e.clientX - centerX;
const offsetY = e.clientY - centerY;
// Compute raw torque (px²/frame)
const rawTorque = offsetX * velY - offsetY * velX;
// Normalize torque so rotation ∝ pointer speed (deg/sec)
const leverDist = Math.hypot(offsetX, offsetY) || 1;
const angularForce = rawTorque / leverDist;
// Calculate and clamp velocities
const velocityX = clampXY(velX * xyMultiplier);
const velocityY = clampXY(velY * xyMultiplier);
const rotationVelocity = clampRot(angularForce * rotationMultiplier);
// Apply GSAP inertia tween
gsap.to(target, {
inertia: {
x: { velocity: velocityX, end: 0 },
y: { velocity: velocityY, end: 0 },
rotation: { velocity: rotationVelocity, end: 0 },
resistance: inertiaResistance
}
});
});
});
});
}
// Initialize Momentum Based Hover (Inertia)
document.addEventListener("DOMContentLoaded", () => {
initMomentumBasedHover();
});
Step 3: Add custom CSS
Step 2: Add custom CSS
Custom CSS in Webflow
Curious about where to put custom CSS in Webflow? Ilja explains it in the below video:
CSS
Implementation
The HTML/CSS is optional for this resource. All you need to do is apply the correct attributes to your existing markup as described below. Once added, the effect will automatically activate on hover-capable devices.
Momentum Container
Add the [data-momentum-hover-init]
attribute to the section that you would like to have elements with the hover effect. The script will look inside for elements to animate and track your mouse speed and position. Make sure to add some extra padding above so the script can properly track your mouse before it enters the element.
Hover Element (wrapper)
Add the [data-momentum-hover-element]
attribute to the element that should respond to the hover interaction. This element listens for the pointer entering, but it won’t animate itself. It triggers the momentum animation on the nested target element instead.
Animated Target
Add the [data-momentum-hover-target]
attribute to the element you want to animate with inertia. This is the part that visually moves when the user hovers — it will respond with x, y, and rotation transforms based on pointer movement and velocity.
Customization options
You can customize how strong or smooth the animation feels by adjusting the following variables at the top of the script. Tweak these values to get the desired responsiveness and physics feel for your project.
const xyMultiplier = 30; // Multiplies pointer velocity for x and y movement
const rotationMultiplier = 20; // Multiplies torque force to determine rotation speed
const inertiaResistance = 200; // Controls how fast the motion eases out (higher = stops quicker)
Resource Details
Last updated
July 7, 2025
Type
The Vault
Category
Hover Interactions
Need help?
Join Slack