Buttons
Button 07

Info

The radial fill flows in and exits from your cursor direction on hover, creating a soft, liquid-like button interaction.

Buttons
May 8, 2026

Required

No items found.

Setup

00

Copy structure to Elementor

Right-click in Elementor, choose “Paste from another site,” and while the popup is open, press cmd/ctrl + v to insert the layout.

Copy To Elementor
Download JSON Template

Important

  • Use Elementor 3.11 or above.
  • Before copying, make sure all required widgets and features are active, including Elementor Pro widgets, Editor v4, and Flexbox Containers.
  • Safari may block clipboard access, so Chrome or Firefox is recommended for smoothest copy/paste experience.
  • If copy/paste fails, clear cache/cookies and disable any plugins or browser extensions that may interfere.
00

Add External Scripts

Place the scripts before the body tag of your project. If you have added them before for another setup, skip this step.

<!-- GSAP Core -->
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15/dist/gsap.min.js"></script>
00

Add Custom CSS

Paste the code through the page or site settings, or add it via Elementor → Custom Code before body tag.

/* click */
[data-oura-button-07="button"] {
  transition: transform 0.2s ease;
}

[data-oura-button-07="button"]:active {
  transform: scale(0.96);
}
00

Add Custom Javascript

Paste the script through Elementor → Custom Code and set it to load after the closing body tag.

document.addEventListener("DOMContentLoaded", () => {
  if (document.body.classList.contains("elementor-editor-active")) return;
  if (window.matchMedia("(hover: none), (pointer: coarse)").matches) return;
  if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
  if (!window.gsap) return;

  const defaults = {
    duration: 0.6,
    ease: "power2.out"
  };

  document.querySelectorAll('[data-oura-button-07="button"]').forEach((button) => {
    const circle = button.querySelector('[data-oura-button-07="circle"]');
    if (!circle) return;

    gsap.set(circle, {
      xPercent: -50,
      yPercent: -50,
      scale: 0,
      transformOrigin: "50% 50%"
    });

    const getCircleData = (event) => {
      const rect = button.getBoundingClientRect();

      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;

      const centerX = rect.width / 2;
      const centerY = rect.height / 2;

      const distanceFromCenterX = Math.abs(x - centerX) / centerX;
      const distanceFromCenterY = Math.abs(y - centerY) / centerY;

      const edgeDistance = Math.max(distanceFromCenterX, distanceFromCenterY);

      const baseSize = Math.sqrt(rect.width ** 2 + rect.height ** 2) * 2;
      const size = baseSize * (1 + edgeDistance * 0.45);

      return { x, y, size };
    };

    button.addEventListener("mouseenter", (event) => {
      const { x, y, size } = getCircleData(event);

      gsap.set(circle, {
        x,
        y,
        width: size,
        height: size
      });

      gsap.to(circle, {
        scale: 1,
        duration: defaults.duration,
        ease: defaults.ease,
        overwrite: true
      });
    });

    button.addEventListener("mouseleave", (event) => {
      const { x, y, size } = getCircleData(event);

      gsap.to(circle, {
        x,
        y,
        width: size,
        height: size,
        scale: 0,
        duration: defaults.duration,
        ease: defaults.ease,
        overwrite: true
      });
    });
  });
});
00

Publish and preview live

Some solutions only work on the live site. Always publish and test after each change, as results may not appear in the editor.