Fix GSAP Page-Load Flicker in Webflow

Intermediate 22:29 webflowgsapanimationpage-loadcss

Kill the flash of unstyled content before a GSAP page-load animation in Webflow with a reusable CSS-plus-attribute pattern that stays safe when JavaScript is off.

Key takeaways

  • The flicker is a timing gap: for a frame the browser paints your elements in their final CSS state before GSAP applies the animation's initial values, and the eye catches that jump.
  • The fix is to hide the wrapper, not each element — set its opacity to 0 so nothing inside can flash, then let GSAP switch it back on at the exact moment it takes control.
  • Put the CSS in the page's <head>, never in the Designer (it'd hide your work) and never via GSAP (that just moves the flicker to the wrapper).
  • A custom attribute like remove-flicker beats a list of class selectors — one rule targets every element that carries it, combo classes and all.
  • Scope the rule to .w-mod-js so it only runs when JavaScript is alive; if JS is off, GSAP never runs and your content must stay visible instead of hidden forever.

Video chapters

  1. 00:00 Intro
  2. 01:30 Breaking down the animation
  3. 07:14 Understanding the flicker on page load
  4. 09:44 How to fix the flicker: the CSS approach
  5. 18:01 What to do when JavaScript is disabled
  6. 20:34 Outro

You can get a perfectly clean GSAP page-load animation in Webflow — no flash, no jump — with a small, reusable pattern you drop into any project. Webflow now ships automatic FOUC handling for GSAP interactions, and it covers a lot of cases. But on heavier pages and more complex layouts you can still catch a flicker on that very first load, and this is how you take full control of it.

The trick isn’t a hack. It’s understanding one small timing gap between when the browser paints the page and when GSAP applies the initial states of your animation — and closing it with three lines of CSS plus a single GSAP action. Once you see why it happens, you’ll reach for the same fix every time.

How it works

When GSAP drives a page-load animation, it needs a brief moment after the page starts rendering to apply the initial conditions — the starting opacity, position, or transform each element animates from. Until that moment arrives, the browser has nothing to go on but your normal Webflow styles, so it paints the elements in their final state. Then GSAP kicks in, snaps them to the animation’s starting point, and plays. That snap — final state, then suddenly the start state — is the flicker. The heavier the page, the longer the browser takes to get to GSAP, and the more obvious the flash becomes.

So the fix is to hide things until GSAP is ready. The instinct is to hide every animated element, but that gets messy fast. Instead, hide the innermost wrapper that contains all of them: wide enough to cover everything in the animation, narrow enough that you’re not blacking out unrelated parts of the page. Set that wrapper’s opacity to 0 and nothing inside it can flash.

Where you put that CSS matters. Not in the Designer — the wrapper would be invisible while you work. Not inside the GSAP interaction — GSAP still needs its moment, so you’d just move the flicker onto the wrapper. It goes in the page’s <head>, which the browser reads and applies before it paints the content. By the time anything appears on screen, the wrapper is already at opacity 0.

The last piece is safety. Your CSS hides the wrapper, but something has to reveal it — and that something is GSAP, which knows exactly when the animation is ready. If a visitor has JavaScript disabled, GSAP never runs, so you must make sure the hide rule never runs either. Otherwise the content stays invisible forever. Webflow gives you a clean hook for that: the w-mod-js class.

How to use it

  1. Find the wrapper(s) to hide. Pick the innermost container(s) that hold every animated element. In the demo the animated elements live in two places — the navbar and the hero — so instead of hiding the whole page wrapper, we target two: the nav wrapper and the video section.

  2. Tag them with a custom attribute. Rather than juggle class and combo-class selectors, give each wrapper the same custom attribute — name it remove-flicker (no value needed). Apply it to the first element, then copy-paste it onto the others.

  3. Hide them from the <head>. In Page Settings → Inside <head> tag, add a style block that targets the attribute and scopes it to JavaScript being active:

    <style>
      .w-mod-js [remove-flicker] {
        opacity: 0;
      }
    </style>

    [remove-flicker] matches every element carrying the attribute, whatever its classes. The .w-mod-js prefix — a class Webflow adds to <html> only when JS is running — means the rule applies only when GSAP will actually bring the elements back.

  4. Reveal them with GSAP. Open your page-load interaction and add a new action (call it remove flicker). Set the target type to Attribute and the attribute name to remove-flicker. Then make it instant: duration 0, start 0, type to, property opacity, value 100%. No easing, no delay — the wrappers flip from invisible to visible the instant GSAP says go.

  5. Publish and test on the live link. The flicker only shows on the published site, so check there — refresh a few times and open it in a new tab. The navbar and headings should now load clean every time.

Resources

Frequently asked questions

Why does my GSAP page-load animation flicker on the published site but not in the Designer?
Because only the live page has real loading times. GSAP needs a beat to apply the animation's starting values, and until it does the browser shows your elements in their normal CSS state — so you see them fully, then they jump to the start of the animation. The Designer and preview skip that delay, so the flash never appears there.
How do I hide elements before a page-load animation without breaking the Webflow editor?
Don't set the opacity in the Designer or inside the interaction. Add the rule in Page Settings → Inside <head> tag instead, so the browser applies it before the page paints while your Designer view stays fully visible and editable.
What does the .w-mod-js class do in Webflow?
Webflow adds w-mod-js to the <html> element only when JavaScript is running. Scoping your hide rule to it means the elements are hidden only in the exact situation where GSAP will bring them back — if scripts are blocked, nothing gets hidden and your content stays on screen.
Do I still need this if Webflow now handles FOUC automatically?
Webflow's automatic FOUC handling covers most simple cases, so try without the pattern first. Reach for this controlled approach on heavier pages or complex layouts where a small flash still slips through.

← Back to the course