Jump to content
Search Community

ScrollSmoother doesn't work in Elementor editor in WordPress

Skilltech test
Moderator Tag

Recommended Posts

In WordPress, in Elementor's editor, when ScrollSmoother is initiated, the page cannot be scrolled.

 

That is a HUGE problem. Basically renders ScrollSmoother useles in the most used WordPress plugin.

If you have some pull with them you should press them to fix it or if you can do something on your end that would also work.

 

CodePen is inapplicable. You need WordPress installed, then Elementor plugin and then edit the page using "Edit with Elementor". I have GSAP, ScrollTrigger, ScrollSmoother and ScrollToPlugin running. And of course smooth-wrapper and smooth-content.

 

I'm "wordpressing" a HTML website which works perfectly fine so there are no bugs. Also, the final published page in WordPress works fine. The issue is ONLY present when the page is being edited with Elementor. When "smooth" is changed to zero, the page becomes scrollable but none of the scrollTrigger animations work.

 

gsap.registerPlugin(ScrollTrigger, ScrollSmoother);

let smoother = ScrollSmoother.create({
	smooth: 2, // seconds it takes to "catch up" to native scroll position
	effects: true // look for data-speed and data-lag attributes on elements and animate accordingly
});

 

Link to comment
Share on other sites

UPDATE:

 

It's still a huge issue but I've shamelessly patched it.

 

Since Elementor's editor is iframing the final page which is being edited, your code for some reason stops working but just for the heck of it I tried wrapping the, get this, iframe in #smooth-wrapper and #smooth-content and it worked. I guess your JS is somehow breaking out of the iframe???

 

Since I have access to the Editor page, which is the parent of the iframe, I waited for it to generate the iframe and then did the wrapping.

 

Here is the code if someone needs to patch it until the issue is fixed (I also noticed that console warnings and errors are now doubled but everything else's running fine).

 

jQuery(document).ready(function($) {
  "use strict";

  function patchGSAPElementorConflict() {

    var i = 0;
    var checkIfIframeIsLoaded = setInterval(function() {

      if ( $( '#elementor-preview-iframe' ).hasClass( 'iframe-loaded' ) ) {

        // addClass (below) performed successfully, exit!

        window.clearInterval(checkIfIframeIsLoaded);

      } else if (++i === 50) {

        // Still no target to addClass to after 15 seconds, something's wrong with page load, exit!

        window.clearInterval(checkIfIframeIsLoaded);

      } else {

        /**
         * Target found
         */

        // #1 Adding the class to use to clearInterval
        // #2 Making the iframe fullheight (wrapping it with #smooth-wrapper below would colapse it otherwise)

        $( '#elementor-preview-iframe' ).addClass( 'iframe-loaded' ).css( 'min-height', '100vh' );

        // wrapping the iframe with smooth-wrapper and smooth-content

        $( '#elementor-preview-iframe' ).wrap( '<div id="smooth-wrapper" class="pushable-content"></div>' );
        $( '#smooth-wrapper' ).wrap( '<div id="smooth-content"></div>' );

      } 

    }, 300);

  }

  window.onload = () => {
    patchGSAPElementorConflict();	
  };

});

 

Link to comment
Share on other sites

Hm, I'm not familiar with Elementor and I don't have access to a way to test what you're talking about which makes it awkward to offer an answer. I'm pretty sure ScrollSmoother can't "reach outside" the iframe that it's in (browsers don't allow that for security reasons). For example, look at any CodePen demo in these forums that uses ScrollSmoother - it is very much contained within that iframe and causes no issues. I'm really not sure how Elementor is doing its previewing and I'm glad to hear that you created a workaround in your setup. 

 

I wish I could see something in the browser illustrating the issue you're running into so that I could poke around a bit. 

 

I'm curious - if you set smooth: 0 (just for the preview), does that solve things (except obviously it wouldn't have smoothing)? 

Link to comment
Share on other sites

With 5+ million active installations I think Elementor might deserve a test run. The real number is probably much higher, 5+ million is just a cap number on wordpress .org

To test, all you'd need is WordPress running (free) and Elementor running (also free).

 

20 minutes ago, GreenSock said:

can't "reach outside" the iframe

I know that, and it looks pretty illegal.

 

As for smooth: 0, I alredy tried and wrote it down.

2 hours ago, Skilltech said:

When "smooth" is changed to zero, the page becomes scrollable but none of the scrollTrigger animations work.

That's not really acceptable.

 

UPDATE 2: With further testing, when I wrap the <iframe> with a single generic <div>, that also fixes the scrolling (but also doubles the warnings and erros in the console).

Link to comment
Share on other sites

Based on your description, it sounds like you may be applying the ScrollSmoother/Trigger to the wrong content(?) By default, ScrollTrigger will use the main page (body/html) as the "scroller" - that's the thing whose scrollbar it watches in order to figure out positioning. So if you've got an iframe instead that is doing the actual scrolling, it would make sense that none of the ScrollTriggers would fire because the page's scrollbar isn't going anywhere - the iframe's is. Does that make sense? 

 

And are you sure it's an iframe? I wonder if it's just a regular <div> that has overflow set to allow scrolling which would explain the behavior you described. 

 

ScrollSmoother is designed to work on the whole page (not a sub-element that has its own scrollbar). So if Elementor's preview system depends on a setup where it is creating a sub-element and injecting scrollable content in there, I don't think it's feasible to "fix" (at least not with a pretty huge rewrite and even then I'm not sure it'd work or be worthwhile, especially if it's **only** for previewing in Elementor and it works fine on the published site).

 

You could see if setting smoothing to 0 and adding a line like this resolves things for your ScrollTriggers at least (not ScrollSmoother):

ScrollTrigger.defaults({
  scroller: "#your-element-that-has-the-scrollbar"
});

 

Link to comment
Share on other sites

39 minutes ago, GreenSock said:

you may be applying the ScrollSmoother/Trigger to the wrong content(?)

As I've said, I'm working with a fully working code (with gsap + ScrollSmoother installed) with 0 errors.

 

39 minutes ago, GreenSock said:

are you sure it's an iframe?

Yes

 

39 minutes ago, GreenSock said:

especially if it's **only** for previewing

I wouldn't say "only" for previewing when that's where people need to build their website. Otherwise they'd be blind or crippled.

 

39 minutes ago, GreenSock said:
scroller: "#your-element-that-has-the-scrollbar"

Doesn't help. No change with ScrollTrigger.

 

UPDATE 3: I also tried .detach() and (re) .attach() of the iframe and that removes the issue as well (again, with doubled warnings etc. in the console).

 

Question: can I restart ScrollSmoother when #smooth-content div's height changes? I think it also plays a part in Elementor. When I drop a new tall widget (like a full-height section)(widget = Elementor editor/page builder elements), I see that the scrolling is working but not going all the way down (as though the ScrollSmoother is not aware of the new height).

 

 

Link to comment
Share on other sites

40 minutes ago, Skilltech said:

Question: can I restart ScrollSmoother when #smooth-content div's height changes? I think it also plays a part in Elementor. When I drop a new tall widget (like a full-height section)(widget = Elementor editor/page builder elements), I see that the scrolling is working but not going all the way down (as though the ScrollSmoother is not aware of the new height).

 

Try calling ScrollTrigger.refresh() once you're done making changes to the DOM (layout is settled). 

 

41 minutes ago, Skilltech said:

As I've said, I'm working with a fully working code (with gsap + ScrollSmoother installed) with 0 errors.

 

Right, but I though you said it's only broken in "preview" (building) mode in Elementor, right? So obviously something is different between the official vs preview version, and my guess is it's related to Elementor wrapping things in an odd way (you said an iframe, and if that's the case it should be fine as long as you're running the ScrollTrigger/ScrollSmoother stuff INSIDE that iframe rather than the container page). 

Link to comment
Share on other sites

40 minutes ago, Skilltech said:

can I restart ScrollSmoother when #smooth-content div's height changes?

I fixed that as well. Here's the code:

var elem = $( "#smooth-content" )[0];
	
let resizeObserver = new ResizeObserver(() => {
  smoother.kill();
  smoother = ScrollSmoother.create({
    smooth: 2, // seconds it takes to "catch up" to native scroll position
    effects: true // look for data-speed and data-lag attributes on elements and animate accordingly
  });
});

resizeObserver.observe(elem);

 

Link to comment
Share on other sites

4 minutes ago, GreenSock said:

as long as you're running the ScrollTrigger/ScrollSmoother stuff INSIDE that iframe

It is inside that iframe and only inside that iframe. I described it in detail above. The thing is that when editing, you are on the editor page, and "final" page is in the iframe, BUT it's updating in real-time, so they are connected with some JS magic. Or elementor is building an instance of that final page but it's not really the actual page and that particular instance is somehow being affected by the editor page.

 

8 minutes ago, GreenSock said:

Try calling ScrollTrigger.refresh() once you're done making changes to the DOM (layout is settled). 

I was talking about ScrollSmoother, not Trigger. But I might as well refresh ScrollTrigger, it's a good idea. ScrollSmoother could also benefit from its own .refresh() method.

 

Anyway, the patch is now doing its job. So, until Elementor guys fix that conflict, ScrollTrigger/GSAP users won't be very happy.

Link to comment
Share on other sites

6 minutes ago, Skilltech said:

I was talking about ScrollSmoother, not Trigger. But I might as well refresh ScrollTrigger, it's a good idea. ScrollSmoother could also benefit from its own .refresh() method.

ScrollSmoother is built on TOP of ScrollTrigger - think of it like just a specialized ScrollTrigger (because, well, that's exactly what it is). Literally it creates a ScrollTrigger for the whole page and scrubs its "animation" (which is the visual scroll position). That's why I said to call ScrollTrigger.refresh(), because that'll force the ScrollSmoother to adjust its sizing/positioning accordingly. There's no point in adding a ScrollSmoother.refresh() method because all it would do is call ScrollTrigger.refresh() :)

 

Your solution with the ResizeObserver could probably be simplified to call ScrollTrigger.refresh(), but you might want to delay it by using a requestAnimationFrame() or setTimeout() because when you ScrollTrigger.refresh(), it must roll back changes, unpin things, and use the page's natural layout to ensure everything is accurate, thus you wouldn't want it to get stuck in an endless loop where ScrollTrigger's refresh() is causing things to resize (temporarily) which then triggers the ResizeObserver which triggers the refresh(), etc. 

 

Thanks for sharing your solutions so that other Elementor users can avoid pulling their hair out. 👍

Link to comment
Share on other sites

I'd try something like this: 

let resizeObserver = new ResizeObserver(() => ScrollTrigger.isRefreshing || ScrollTrigger.refresh());

resizeObserver.observe($( "#smooth-content" )[0]);

That won't, however, look for new "effects" like if you added something that has data-speed or data-lag, for example. So if you need that, just stick with your original "fix" of killing the current ScrollSmoother and recreating a new one. 

Link to comment
Share on other sites

  • 3 months later...

@Warren_A I've put the opening divs in my header.php and the closing divs in footer.php, assuming you're building your own theme as I am.

 

<!-- opening tags in header.php -->
<div id="smooth-wrapper">
	<div id="smooth-content">
      
	<!-- closing tags in footer.php -->
      </div><!-- #smooth-content -->
</div><!-- #smooth-wrapper -->

<!-- 
	Opening tags go at the bottom of the header.php
	TIP: any "position: fixed;" elements you should put outside these tags (before opening them).

	Closing tags go right before <?php wp_footer(); ?>
	and </body> closing tag.
	And your overall HTML structure should be correct
	i.e. no unclosed divs or too many closed divs by mistake.
-->

 

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...