New: Claude Design to Webflow workflow now available → Read the guide
GSAP to Webflow Guide

How to Convert GSAP to Webflow Interactions

Write GSAP in a mapping-friendly way so Flowboard can convert simple animation intent into native Webflow IX3 while preserving harder GSAP as runtime or fallback code.

Flowboard prioritizes correctness over native coverage. If a GSAP block cannot be represented safely as Webflow IX3, it stays supplemental instead of becoming misleading native output.

Memberstack

Memberstack published a detailed walkthrough showing how Flowboard can fit into an AI to GSAP to Webflow workflow.

Watch the Memberstack tutorial

Best-results checklist

  • Use literal class or ID selectors for animated targets.
  • Keep values literal and explicit.
  • Prefer gsap.from(...), gsap.fromTo(...), and simple gsap.timeline(...) chains.
  • For color/background tweens, use fromTo(...) or seed a start state with gsap.set(...).
  • Keep native-safe GSAP in separate <script> blocks from plugins, callbacks, dynamic selectors, and app logic.
  • For fallback GSAP tests, make sure the element, CSS, and GSAP selector use the same literal class.
  • Check gsapWarnings after conversion. Warnings explain why Flowboard preserved fallback GSAP.

What maps natively

Static tween targets

Flowboard supports gsap.to(...), gsap.from(...), and gsap.fromTo(...) when the target is static and the properties are supported.

gsap.to(".box", { x: 100, opacity: 0.5, duration: 0.4 });

gsap.from(".card", { y: 24, opacity: 0, duration: 0.5 });

gsap.fromTo(
  ".hero-title",
  { y: 32, opacity: 0 },
  { y: 0, opacity: 1, duration: 0.7, ease: "power3.out" }
);

Transform values

Supported transforms include numeric values and safe string units. Flowboard maps x/y pixel strings to numeric pixels, percent x/y strings to xPercent/yPercent, and degree strings to numeric rotation values.

gsap.to(".box", {
  x: "20px",
  y: "-20px",
  xPercent: 100,
  rotation: "-45deg",
  scale: 1.1,
  scaleX: 0.95,
  scaleY: 1.05
});

gsap.to(".panel", { x: "100%", y: "-100%" });

Opacity and style properties

Opacity maps as a transform-style IX3 property. Supported color/style properties can map when Flowboard has a safe start and end state.

gsap.to(".box", { opacity: 0 });

gsap.fromTo(
  ".badge",
  { backgroundColor: "#111827", color: "#ffffff" },
  { backgroundColor: "#ffffff", color: "#111827", duration: 0.25 }
);

gsap.set(".badge", { backgroundColor: "#111827" });
gsap.to(".badge", { backgroundColor: "#ffffff", duration: 0.25 });

Direct style-only to(...) tweens without a known start state are preserved as fallback to avoid native output plus residual GSAP replaying the same visual behavior.

Common AI wrappers

Flowboard can unwrap common static wrappers that AI tools often generate.

document.addEventListener("DOMContentLoaded", () => {
  gsap.to(".box", { x: 100 });
});

(() => {
  gsap.from(".hero", { opacity: 0, y: 20 });
})();

gsap.context(() => {
  gsap.to(".card", { y: 0, opacity: 1 });
});

Static selector aliases

Literal selector aliases can map when the selector source is direct and static. Flowboard intentionally does not propagate arbitrary variables such as const selector = ".box"; document.querySelector(selector).

const box = document.querySelector(".box");
gsap.to(box, { x: 100 });

const cards = document.querySelectorAll(".card");
gsap.to(cards, { opacity: 1 });

const hero = document.getElementById("hero");
gsap.to(hero, { y: 20 });

const items = gsap.utils.toArray(".item");
gsap.from(items, { opacity: 0, y: 20 });

const q = gsap.utils.selector(".scope");
gsap.to(q(".child"), { x: 100 });

Safe forEach loops

Simple loops can map when the loop variable comes directly from a literal selector collection and tween values do not depend on index, dataset, conditionals, computed values, or external state.

document.querySelectorAll(".card").forEach((card) => {
  gsap.to(card, { opacity: 1, y: 0 });
});

gsap.utils.toArray(".tile").forEach((tile) => {
  gsap.from(tile, { opacity: 0, y: 20 });
});

Timeline labels and positions

Static labels and relative timeline positions can map. Supported positions include <, >, <+=0.2, >-=0.2, label, label+=0.2, and label-=0.2.

const tl = gsap.timeline();

tl.to(".a", { x: 100, duration: 1 })
  .addLabel("mid")
  .to(".b", { y: 100, duration: 1 }, "mid+=0.2")
  .to(".c", { opacity: 0 }, "<");

Click and hover controls

const panelTl = gsap.timeline({ paused: true, reversed: true });
panelTl.fromTo(".panel", { xPercent: 100 }, { xPercent: 0, duration: 0.35 });

document.querySelector(".panel-toggle").addEventListener("click", () => {
  if (panelTl.reversed()) {
    panelTl.play();
  } else {
    panelTl.reverse();
  }
});

Basic safe ScrollTrigger

Basic ScrollTrigger config can map when it uses static selectors and safe options.

gsap.fromTo(
  ".feature-card",
  { y: 40, opacity: 0 },
  {
    y: 0,
    opacity: 1,
    duration: 0.8,
    scrollTrigger: {
      trigger: ".feature-card",
      start: "top 80%",
      end: "bottom 40%",
      scrub: true
    }
  }
);

What intentionally falls back

Flowboard preserves runtime/fallback GSAP for behavior that cannot be represented faithfully as native IX3.

  • Unsupported transform units: rem, em, vh, vw
  • These units are preserved as fallback because their pixel value depends on runtime CSS, viewport size, or browser settings. Flowboard does not guess those values for native IX3.
  • Expressions: calc(...), var(...), mixed CSS expressions, and template expressions.
  • Unsupported string scale values.
  • Unsupported direct style properties such as filter.
  • Callbacks: onStart, onUpdate, onComplete, and function-valued payloads.
  • keyframes, repeat, repeatDelay, repeatRefresh, and yoyo.
  • Unsafe or advanced ScrollTrigger behavior such as pin, snap, callbacks, non-literal config, custom scrollers, or variable references.
  • Dynamic selectors, string concatenation selectors, function-returned selectors, and selector variables from external state.
  • Loops that depend on index, dataset, computed values, conditionals, nested dynamic selectors, or external state.
  • Unresolved labels, dynamic position variables, computed timeline positions, tl.call(...), complex tl.add(...), and callback labels.
  • Unsupported plugins such as MotionPathPlugin, Flip, Draggable, MorphSVGPlugin, ScrollSmoother, Observer, and InertiaPlugin.

Examples that fall back

gsap.to(".box", { x: "10rem" });
gsap.to(".box", { filter: "blur(4px)" });
gsap.to(".box", { opacity: 0, repeat: -1, yoyo: true });
gsap.to(document.querySelector(`.${name}`), { x: 100 });

document.querySelectorAll(".card").forEach((card, i) => {
  gsap.to(card, { delay: i * 0.1, opacity: 1 });
});

const tl = gsap.timeline();
tl.to(".a", { x: 100 }).to(".b", { filter: "blur(4px)" });

How to split GSAP scripts

Use script block boundaries to keep simple native-safe GSAP away from fallback-only GSAP. This avoids whole-block fallback and duplicate-risk cases where the same original GSAP block would need to be preserved.

Recommended

<script>
  gsap.from(".hero-title", { y: 32, opacity: 0, duration: 0.6 });
  gsap.to(".hero-cta", { scale: 1.05, duration: 0.2 });
</script>

<script>
  gsap.registerPlugin(MotionPathPlugin);
  gsap.to(".orbit-dot", {
    motionPath: { path: "#orbit-path" },
    repeat: -1
  });
</script>

Avoid mixing native-safe and fallback-only GSAP

<script>
  gsap.from(".hero-title", { y: 32, opacity: 0 });
  gsap.to(".orbit-dot", { motionPath: { path: "#orbit-path" } });
</script>

The first script can become native IX3. The second script stays supplemental GSAP. Keeping them separate gives Flowboard the cleanest result without duplicating animation behavior.

Fallback selector classes

When Flowboard preserves a GSAP block as runtime/fallback code, the original GSAP selector still has to find an element on the published page.

For simple literal class selectors, Flowboard preserves the selector class for runtime targeting, even when Webflow displays a different styling class in the Style panel. For example, Webflow may show the element label as motion-card in the Navigator while the active style selector is block. The important runtime check is whether .motion-card still selects the element.

Good fallback test pattern

<div class="motion-card" style="width: 220px; padding: 28px; background: #7c3aed; color: white; border-radius: 12px;">
  Runtime fallback card
</div>

<script>
  gsap.to(".motion-card", {
    x: "8rem",
    rotation: "12deg",
    repeat: -1,
    yoyo: true,
    duration: 0.9,
    ease: "power2.inOut"
  });
</script>

This falls back because rem and repeat/yoyo must be preserved by GSAP, but the selector should still work because the target class is literal and attached to the animated element.

How to tell if mapping worked

  • Check the conversion report for mapped GSAP counts.
  • Review gsapWarnings for deterministic fallback reasons.
  • If a native-safe tween falls back, split it into its own script block and remove dynamic/plugin-heavy behavior.
  • If fallback GSAP does not move, check the published page console with document.querySelector(".your-class"). The class in the Navigator and the active Style panel selector may not be the same thing.
  • Retry one simple tween at a time, then add complexity back.

Prompt for AI-generated GSAP

Generate GSAP that is compatible with Flowboard's HTML-to-Webflow converter.

Rules:
- Use literal class or ID selectors only.
- Prefer direct selectors like .hero-title or simple descendants like .hero .title.
- Use gsap.from, gsap.to, gsap.fromTo, gsap.set, or simple gsap.timeline chains only.
- Use px, %, deg, numeric scale, and numeric opacity values.
- Keep all tween values literal and explicit.
- For color/background changes, use gsap.fromTo or gsap.set before gsap.to.
- Allowed triggers: page load, simple click, simple hover, basic ScrollTrigger.
- Do not use unsupported plugins, callbacks, keyframes, repeat/yoyo, complex selectors, or DOM mutation side effects.
- Put native-friendly GSAP in separate script blocks from plugin-heavy, dynamic, callback, and app logic.