Skip to content
Advertisement

Vertical to horizontal to vertical again scroll effect

I want to make a vertical to horizontal back to vertical scrolling effect that also works on mobile. I have found the following jQuery code snippet:

jQuery(function() {

   jQuery('.horizontal-scroll-wrapper .elementor-container').mousewheel(function(event, delta) {

      if (delta < 0 && this.scrollLeft < this.scrollWidth-$(this).width() ||
          delta > 0 && this.scrollLeft) event.preventDefault();

      this.scrollLeft -= (delta * 1);
   });
});
body {
  margin: 35px;
}

.horizontal-scroll-wrapper .elementor-container {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  margin: 20px 0 40px 0;
}

.horizontal-scroll-wrapper .elementor-container div {
  margin: 0 10px;
  width: 500px !important;
}

.service-wrapper img {
  width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>

<section>
  <div>
    <h2>Content here</h2>
    <p>Vertical Scrolling is up at the top. Once the user gets to the row of images, horizontal scrolling. Then, back to vertical scrolling after horizontal scrolling.
    </p>
    <p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
  </div>
</section>

<section class="elementor-section elementor-top-section elementor-element elementor-element-5e57d97 elementor-section-full_width horizontal-scroll-wrapper elementor-section-height-default elementor-section-height-default" data-id="5e57d97" data-element_type="section">
  <div class="elementor-container elementor-column-gap-default">
    <div class="elementor-column elementor-col-20 elementor-top-column elementor-element elementor-element-37fee73 service-wrapper" data-id="37fee73" data-element_type="column">
      <div class="elementor-widget-wrap elementor-element-populated">
        <div class="elementor-element elementor-element-0ffae83 elementor-widget elementor-widget-image" data-id="0ffae83" data-element_type="widget" data-widget_type="image.default">
          <div class="elementor-widget-container">
            <img src="https://via.placeholder.com/450x350" class="attachment-full size-full" alt="HR Management" width="450" height="350">
          </div>
        </div>
        <div class="elementor-element elementor-element-d4fe169 elementor-widget elementor-widget-spacer" data-id="d4fe169" data-element_type="widget" data-widget_type="spacer.default">
          <div class="elementor-widget-container">
            <div class="elementor-spacer">
              <div class="elementor-spacer-inner"></div>
            </div>
          </div>
        </div>
        <div class="elementor-element elementor-element-38c552f services-title elementor-widget elementor-widget-heading" data-id="38c552f" data-element_type="widget" data-widget_type="heading.default">
          <div class="elementor-widget-container">
            <h2 class="elementor-heading-title elementor-size-default">HR Management</h2>
          </div>
        </div>
        <div class="elementor-element elementor-element-effcadb servcies-exc elementor-widget elementor-widget-text-editor" data-id="effcadb" data-element_type="widget" data-widget_type="text-editor.default">
          <div class="elementor-widget-container">
            <p>We can help with HR Management.</p>
          </div>
        </div>
      </div>
    </div>
    <div class="elementor-column elementor-col-20 elementor-top-column elementor-element elementor-element-48647e0 service-wrapper" data-id="48647e0" data-element_type="column">
      <div class="elementor-widget-wrap elementor-element-populated">
        <div class="elementor-element elementor-element-1a962f0 elementor-widget elementor-widget-image" data-id="1a962f0" data-element_type="widget" data-widget_type="image.default">
          <div class="elementor-widget-container">
            <img src="https://via.placeholder.com/450x350" class="attachment-full size-full" alt="HR Management" width="450" height="350">
          </div>
        </div>
        <div class="elementor-element elementor-element-6830704 elementor-widget elementor-widget-spacer" data-id="6830704" data-element_type="widget" data-widget_type="spacer.default">
          <div class="elementor-widget-container">
            <div class="elementor-spacer">
              <div class="elementor-spacer-inner"></div>
            </div>
          </div>
        </div>
        <div class="elementor-element elementor-element-ed7ce05 services-title elementor-widget elementor-widget-heading" data-id="ed7ce05" data-element_type="widget" data-widget_type="heading.default">
          <div class="elementor-widget-container">
            <h2 class="elementor-heading-title elementor-size-default">Payroll Processing</h2>
          </div>
        </div>
        <div class="elementor-element elementor-element-f9b8f78 servcies-exc elementor-widget elementor-widget-text-editor" data-id="f9b8f78" data-element_type="widget" data-widget_type="text-editor.default">
          <div class="elementor-widget-container">
            Help with compliance and efficency. </div>
        </div>
      </div>
    </div>
    <div class="elementor-column elementor-col-20 elementor-top-column elementor-element elementor-element-bcc5cca service-wrapper" data-id="bcc5cca" data-element_type="column">
      <div class="elementor-widget-wrap elementor-element-populated">
        <div class="elementor-element elementor-element-a1c2bef elementor-widget elementor-widget-image" data-id="a1c2bef" data-element_type="widget" data-widget_type="image.default">
          <div class="elementor-widget-container">
            <img src="https://via.placeholder.com/450x350" class="attachment-full size-full" alt="HR Management" width="450" height="350">
          </div>
        </div>
        <div class="elementor-element elementor-element-2d53af9 elementor-widget elementor-widget-spacer" data-id="2d53af9" data-element_type="widget" data-widget_type="spacer.default">
          <div class="elementor-widget-container">
            <div class="elementor-spacer">
              <div class="elementor-spacer-inner"></div>
            </div>
          </div>
        </div>
        <div class="elementor-element elementor-element-ddfc0ca services-title elementor-widget elementor-widget-heading" data-id="ddfc0ca" data-element_type="widget" data-widget_type="heading.default">
          <div class="elementor-widget-container">
            <h2 class="elementor-heading-title elementor-size-default">Benefits</h2>
          </div>
        </div>
        <div class="elementor-element elementor-element-2670cb7 servcies-exc elementor-widget elementor-widget-text-editor" data-id="2670cb7" data-element_type="widget" data-widget_type="text-editor.default">
          <div class="elementor-widget-container">
            Better benefits.. </div>
        </div>
      </div>
    </div>
    <div class="elementor-column elementor-col-20 elementor-top-column elementor-element elementor-element-ca26df1 service-wrapper" data-id="ca26df1" data-element_type="column">
      <div class="elementor-widget-wrap elementor-element-populated">
        <div class="elementor-element elementor-element-ea43775 elementor-widget elementor-widget-image" data-id="ea43775" data-element_type="widget" data-widget_type="image.default">
          <div class="elementor-widget-container">
            <img src="https://via.placeholder.com/450x350" class="attachment-full size-full" alt="HR Management" width="450" height="350">
          </div>
        </div>
        <div class="elementor-element elementor-element-c54d7f8 elementor-widget elementor-widget-spacer" data-id="c54d7f8" data-element_type="widget" data-widget_type="spacer.default">
          <div class="elementor-widget-container">
            <div class="elementor-spacer">
              <div class="elementor-spacer-inner"></div>
            </div>
          </div>
        </div>
        <div class="elementor-element elementor-element-a17f87c services-title elementor-widget elementor-widget-heading" data-id="a17f87c" data-element_type="widget" data-widget_type="heading.default">
          <div class="elementor-widget-container">
            <h2 class="elementor-heading-title elementor-size-default">Tax Help</h2>
          </div>
        </div>
        <div class="elementor-element elementor-element-c21fff4 servcies-exc elementor-widget elementor-widget-text-editor" data-id="c21fff4" data-element_type="widget" data-widget_type="text-editor.default">
          <div class="elementor-widget-container">
            Help with your tax reporting. </div>
        </div>
      </div>
    </div>
    <div class="elementor-column elementor-col-20 elementor-top-column elementor-element elementor-element-9fb0b6d service-wrapper" data-id="9fb0b6d" data-element_type="column">
      <div class="elementor-widget-wrap elementor-element-populated">
        <div class="elementor-element elementor-element-1afb7f9 elementor-widget elementor-widget-image" data-id="1afb7f9" data-element_type="widget" data-widget_type="image.default">
          <div class="elementor-widget-container">
            <img src="https://via.placeholder.com/450x350" class="attachment-full size-full" alt="HR Management" width="450" height="350">
          </div>
        </div>
        <div class="elementor-element elementor-element-399c80e elementor-widget elementor-widget-spacer" data-id="399c80e" data-element_type="widget" data-widget_type="spacer.default">
          <div class="elementor-widget-container">
            <div class="elementor-spacer">
              <div class="elementor-spacer-inner"></div>
            </div>
          </div>
        </div>
        <div class="elementor-element elementor-element-564366e services-title elementor-widget elementor-widget-heading" data-id="564366e" data-element_type="widget" data-widget_type="heading.default">
          <div class="elementor-widget-container">
            <h2 class="elementor-heading-title elementor-size-default">Workers' Compensation</h2>
          </div>
        </div>
        <div class="elementor-element elementor-element-d6c3a48 servcies-exc elementor-widget elementor-widget-text-editor" data-id="d6c3a48" data-element_type="widget" data-widget_type="text-editor.default">
          <div class="elementor-widget-container">
            Reduce overhead and protect your employees. </div>
        </div>
      </div>
    </div>
  </div>
</section>
<section>
  <div>
    <h2>Here is the bottom section. </h2>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
  </div>
</section>

But it doesn’t work very well on mobile, which is a deal breaker for me. I am looking for something more like these two examples:

https://www.ls.graphics/dsk

https://studiomindset.co.uk

Could anyone help point me in the right direction on how to do this? I’d prefer to accomplish this with vanilla JavaScript but I’m definitely open to all suggestions or code snippets.

Advertisement

Answer

Here’s my vanilla JavaScript solution. It works on mobile as well.

        let lastKnownScrollPosition = 0;
        let deltaY = 0;

        window.addEventListener("scroll", wheelHandler);
        
        document.querySelectorAll('.sticky-container').forEach(function(container) {
            const stikyContainerHeight = (container.querySelector('main').offsetWidth + window.innerHeight);
            container.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');
        });
        

        function isElementInViewport(el) {
            const rect = el.getBoundingClientRect();
            return rect.top <= 0 && rect.bottom > document.documentElement.clientHeight;
        }

        function wheelHandler(event) {

            deltaY = window.scrollY - lastKnownScrollPosition;
            lastKnownScrollPosition = window.scrollY;


            console.log('deltaY', deltaY);


            const containerInViewPort = Array.from(document.querySelectorAll('.sticky-container')).filter(function(container) {
                return isElementInViewport(container);
            })[0];

            if (!containerInViewPort) {
                return;
            }

            var isPlaceHolderBelowTop = containerInViewPort.offsetTop < document.documentElement.scrollTop;
            var isPlaceHolderBelowBottom = containerInViewPort.offsetTop + containerInViewPort.offsetHeight > document.documentElement.scrollTop;
            let g_canScrollHorizontally = isPlaceHolderBelowTop && isPlaceHolderBelowBottom;


            if (g_canScrollHorizontally) {

                containerInViewPort.querySelector('main').scrollLeft += deltaY;

            }
        }
    section {
        min-width: 50vw;
    }

    section:nth-child(even) {
        background-color: teal;
        color: white;
    }
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.17/tailwind.min.css" rel="stylesheet"/>
<div class="h-screen flex items-center justify-center">
        Content Before
    </div>
    <div class="sticky-container">
        <main class="overflow-x-hidden flex sticky top-0">
            <section class="min-h-screen flex items-center justify-center text-5xl">
                <h1>First</h1>
            </section>
            <section class="min-h-screen flex items-center justify-center text-5xl">
                <h1>Second</h1>
            </section>
            <section class="min-h-screen flex items-center justify-center text-5xl">
                <h1>Third</h1>
            </section>
            <section class="min-h-screen flex items-center justify-center text-5xl">
                <h1>Fourth</h1>
            </section>
            <section class="min-h-screen flex items-center justify-center text-5xl">
                <h1>Fifth</h1>
            </section>
            <section class="min-h-screen flex items-center justify-center text-5xl">
                <h1>Sixth</h1>
            </section>
            <section class="min-h-screen flex items-center justify-center text-5xl">
                <h1>Last</h1>
            </section>
        </main>
    </div>
    <div class="h-screen flex items-center justify-center">
        Content After
    </div>
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement