Elementor Full Screen Horizontal Scroll Containers

Elementor Full Screen Horizontal Scroll Containers

Just launched! Checkout the CSS Course for Elementor users.

Table of Contents

In this tutorial you are going to learn how to create horizontally scrolling Elementor containers  without any plugin.

This tutorial uses the new containers element, as they are perfect for this.

See the demos here.

Straight code version (desktop and mobile ready):


GSAP version (desktop only)


GSAP with snapping version (desktop only)


  • Make any content at all horizontally scrollable
  • Works on desktop and mobile
  • Performant animation
  • No JS dependencies version
  • GSAP version
  • Snapping enabled option
  • RTL compatible

Important note: You will need the feature "Container" to be enabled under Elementor > Experiments > Container. This uses the new Container element.

Template included: The "Straight code" demo above is included as a template JSON file. The GSAP versions are not included as template files, but easy to replicate by following the tutorial.

Let's get started!

First, add an Elementor container to your page

This is a premium tutorial. Purchase access to unlock the full tutorial and download the template.


Element.how also provides premium tutorials showing awesome advanced designs, check them out here.

Looking for something else? Search across 2445 Elements right here:

Checkout the Elementor Addon Finder directly


29 Responses

    1. Hey Paul!

      This is a bit complex, and above the scope of the tutorial. The tutorial is made to work with containers that are 100vw by 100vh, so that it's relatively simple and straightforward to use in the editor.

      Changing this, while possible, makes it wonky in the editor, so that's why I don't officially support it.

      However for adventurous users, both code snippets actually support this (varying containers sizes) out of the box.

      Here is how you can play with this:

      On the containers that are direct child of the horizontalScroll_translateContainer, in their advanced > custom CSS field, add this CSS, and adjust to your liking:

      selector {
      width: 70vw;
      max-width:70vw !important;
      min-width:70vw !important;

      In the editor, it will be easier to edit things if you use values that are under 100vw, instead of above. In any case, both should work.

      Different containers can have different widths.

      Hope this helps!

  1. Hi Maxime,

    in that layout (gsap version) would be possible to make a background or a container fixed/sticky in order to have an overlap effect playing with z-index?

    1. Hey,

      Not really no... not as it is at least. With extra work, it would be possible, however it is above the intended scope of this tutorial. It becomes quite specific and would rather be custom work.

      1. No problem Maxime, I've found that is possible to use fixed or absolute positioning placing that items in "horizontalScroll_innerWrapper".
        Even elementor motion effects works with GSAP setting the effect relative to "Entire Page".

      2. Alright I'm glad you found a solution that works for your use case!

        Thanks for sharing!

    1. Hey Sandra!

      Try importing my template in a new page, and then swapping all the code in the HTML element with the GSAP code.

      Let me know if that works properly.

    1. Sorry Mirko, this isn't possible.

      I had a good look at this and the problem with locomotive scroll is that it is very incompatible with Elementor. It breaks nearly every scroll related features of Elementor, such as entrance animations, scrolling effects, anchors smooth scroll, etc.

      To prevent adding smooth scroll, but creating a host of problems, I opted to go with stability instead.

    1. It's possible, however due to the all the DIVs generated, it's not a really good idea. That's why this tutorial is only about how to do it with the containers.

    1. Hey Louise!

      The problem is that your containers, for some reason, aren't display:flex; but they are display:block;

      It's the clear what the reason is... I suspect maybe your optimization plugin. It's as if some CSS is missing.


      .e-container, .e-con { display: flex;}

      should fix the problem


      1. That sorted it! Thank you 🙂 Was my caching plugin as well I suspect - minifying CSS maybe, taken that off

    1. Hey Nicholas!

      The "Shop now" button just has a "#" link that scrolls back up to the top of the page.

      Unfortunately with this design it's not easily possible to have a button to scroll to a specific scroll section. With extra JS this might be possible but it's out of the intended scope of the tutorial....


  2. I got this working on my container with 4 inner containers using the straight code version (works great) but it completely hoses my elementor nav menu. Not a 3rd party elementor addon menu widget but the native elementor menu widget.

    Without your code active, scrolling the single page website will add the class 'active' to the menu item that is in view and remove it when that section scroll out of view (just as you'd expect). With your code active, the first menu item remains active no matter where I scroll to, and the anchor links themselves no longer function properly/take the user to the correct section, or it takes the user nowhere at all. When I deactivate your code (save elementor custom code as draft) the nav menu works fine again. https://kwicks.flywheelsites.com/
    Any help?

    No caching plugins, no optimization, no minification, brand new Hello theme install. No elementor add on plugins. Thanks

  3. Hi, I've been using the horizontal scroll for some time and it worked great until the last version of Elementor.

    Since version 3.8.0 it doesn't work at all, is there an update coming soon to fix this?

    1. Hey Mounir!

      Indeed there has been class names changes with 3.8 that breaks the code slightly. Please replace "e-container" with "e-con" in these two lines of code:

      let scrollSectionsAmount = parentOfStickySection.querySelectorAll('.horizontalScroll_translateContainer > .e-container').length;
      .horizontalScroll_innerWrapper>.horizontalScroll_translateContainer>.e-container {

      To work with Elementor 3.8 and above, they should be:

      let scrollSectionsAmount = parentOfStickySection.querySelectorAll('.horizontalScroll_translateContainer > .e-con').length;
      .horizontalScroll_innerWrapper>.horizontalScroll_translateContainer>.e-con {

      You can simply copy paste the code from the tutorial, it's updated to work with 3.8. Writing here the changes needed for reference.

      Also note that the "horizontalScroll_parent", "horizontalScroll_innerWrapper" and "horizontalScroll_translateContainer" containers needs to be set to "full width" layout, and not boxed.

      1. Hi Maxime,

        Thanks a lot for your answer. I'm going to put it in place right away.

  4. Hi Maxime,

    I've updated by myself the code when elementor 3.8 went out and replaced "e-container" with "e-con" in the JS script and all is working fine but if I copy/paste all the new code It doesn't work at all.
    There are other changing in that file:


    let options = {
    x: () => -(translateXSection.scrollWidth - window.innerWidth),
    ease: "none",
    scrollTrigger: {
    trigger: parentOfStickySection,
    pin: true,
    scrub: 1,
    invalidateOnRefresh: true,
    /* snap: 1 / (scrollSectionsAmount - 1), */
    end: () => "+=" + (translateXSection.scrollWidth - window.innerWidth),

    let anim = gsap.to(translateXSection, options);

    -old one:

    let options = {
    x: -(scrollSectionsAmount - 1) * window.innerWidth,
    ease: "none",
    scrollTrigger: {
    trigger: parentOfStickySection,
    pin: true,
    scrub: 1,
    /* snap: 1 / (scrollSectionsAmount - 1), */
    end: "+=" + (scrollSectionsAmount - 1) * window.innerWidth,

    let anim = gsap.to(translateXSection, options);

    By the way elementor 3.9 beta 2 breaks it (no scroll snapping and other issue) but I don't see any major changelog.



  5. Regarding my previous comment:

    1) code is just fine

    2) elementor 3.9 beta 2 breaks the design due to the added CSS transition rules to e-con
    (I don't know if it will be fixed in future because they added it to implement transform at a containel level)

    3) To fix it I simply added:

    .e-con {
    transition: none;

    1. Hey Shahar! Hope you are well!

      Indeed I see the issue... it looks like it's from some brand new CSS Elementor added in 3.9.0 ! They added a transition on the containers, for the "transform" property, and it results in this little glitch. I updated the code in the tutorial to avoid this issue.


      PS. Other readers seeing this: it's valid for the GSAP version only. Update your code if you have updated to 3.9.0 please.

Leave a Reply