Copied SVG to clipboard
Something went wrong
Copied code to clipboard
Something went wrong
Saved to bookmarks!
Removed from bookmarks

Default

User image

Default

Name

  • -€50
    Upgrade to Lifetime
The Vault/

Momentum Based Hover (Inertia)

Momentum Based Hover (Inertia)

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

Copy
<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

Copy

<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

Copy
.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

Copy
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

Copy

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

Hover
Momentum
Inertia
Cursor
Card
Animation
Movement

Original source

Dennis Snellenberg

Creator Credits

We always strive to credit creators as accurately as possible. While similar concepts might appear online, we aim to provide proper and respectful attribution.