Unable to scroll horizontally beyond 200 viewport widths

I'm facing an issue with my code that switches between vertical and horizontal scrolling but seems to have a width limit of 200vw. When I set the min-width to 50vw, only 4 sections are visible, whereas setting it to 100vw (as shown in the example) displays only 2 sections.

I can't seem to display anything over 200vw, and I'm not sure why that is or how to fix it. Here's the code snippet:

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;


            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;

            }
        }
html,
    body {
        margin: 0;
        font-family: sans-serif;
    }

    .vertical-section {
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    main {
        overflow-x: hidden;
        display: flex;
        position: sticky;
        top: 0;
    }

    h1 {
        margin: 0;
        padding: 0;
    }

    section {
        min-width: 100vw; /*Works perfectly when it's 50vw*/
        min-height: 100vh;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 4ch;
    }

    section:nth-child(even) {
        background-color: teal;
        color: white;
    }
<div class="vertical-section">
        Content Before
    </div>
    <div class="sticky-container">
        <main>
            <section>
                <h1>First</h1>
            </section>
            <section>
                <h1>Second</h1>
            </section>
            <section>
                <h1>Third</h1>
            </section>
      <section>
                <h1>Fourth</h1>
            </section>
      <section>
                <h1>Fifth</h1>
            </section>
            <section>
                <h1>Last</h1>
            </section>
        </main>
    </div>
    <div class="vertical-section">
        Content After
    </div>

I need help understanding this issue and finding a solution. Can anyone assist me?

Answer №1

When scrolling along the Y axis => up/down, the distance of scroll from left to right, or the X axis, is determined by the height you are calculating in the forEach loop for stikyContainerHeight.

For instance, if your container is 500px wide using the 100vw css rule, and there are a total of 6 elements with 5 extending beyond the fold on the right side, this would amount to (500px * 6 = 3000px). To display all 3000px when scrolling down in height, the height must match in pixels. You can sum up the widths of the main section's children elements or multiply the screen width by the number of parent sections' children.

The scrollable height should only add enough distance to scroll two divs on the X axis. If you want to scroll the entire distance, find the width of the whole parent element, multiply it by the sections being scrolled, and apply it to the stikyContainerHeight variable.

let lastKnownScrollPosition = 0;
let deltaY = 0;

// changed to a single query
const main = document.querySelector('.sticky-container'); 

// get the section elements so we can use its nodelist arrays length
const sec = document.querySelectorAll('.sticky-container section'); 

window.addEventListener("scroll", wheelHandler);

// no need for the forEach loop as there is only one element witht he class sticky-container
const stikyContainerHeight = main.getBoundingClientRect().width * sec.length;
main.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');

// everything below here is the same
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;


  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;

  }
}
html,
body {
  margin: 0;
  font-family: sans-serif;
}

.vertical-section {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

main {
  overflow-x: hidden;
  display: flex;
  position: sticky;
  top: 0;
}

h1 {
  margin: 0;
  padding: 0;
}

section {
  min-width: 100vw;
  /*Works perfeclty when it's 50vw*/
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 4ch;
}

section:nth-child(even) {
  background-color: teal;
  color: white;
}
<div class="vertical-section">
  Content Before
</div>
<div class="sticky-container">
  <main>
    <section>
      <h1>First</h1>
    </section>
    <section>
      <h1>Second</h1>
    </section>
    <section>
      <h1>Third</h1>
    </section>
    <section>
      <h1>Fourth</h1>
    </section>
    <section>
      <h1>Fifth</h1>
    </section>
    <section>
      <h1>Last</h1>
    </section>
  </main>
</div>
<div class="vertical-section">
  Content After
</div>

You can also iterate over the sections themselves and sum up their values in a forEach loop.

let stikyContainerHeight = Number();

sec.forEach(s => stikyContainerHeight += s.getBoundingClientRect().width);

main.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ways to eliminate spacing underneath alerts in Bootstrap 5

Currently, I am working on Ruby On Rails and incorporating Bootstrap 5 into my .html.erb file. I noticed that there is extra padding: that includes additional padding How can I achieve a similar result like this: enter image description here Here&apos ...

Leverage Node.js/Express backend objects within frontend JavaScript

I'm new to programming and feeling a bit lost. I've been struggling to find a solution for my issue despite spending a lot of time searching. Currently, I am working on coding a prototype for a simple web app using Node.js, Express, MongoDB, and ...

What could be causing my search form to fail to perform the search initially?

Isn't it strange that my search form doesn't work correctly the first time? You have to search again for it to function properly. Is there something wrong with my code? Fiddle HTML <form id='sform' action="/admin/search.php" metho ...

Is it necessary to use a while loop instead of a for loop when iterating through and removing values from a JavaScript array?

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; function checkOdd(value) { return value % 2; } for (let i = 0; i < array.length; i++) { if (checkOdd(array[i])) { array.splice(i, 1); i--; } } The provided code snippet examines a ...

Showing error message when utilizing the search bar and autocomplete feature (material design CSS)

I'm having difficulty setting up a materialize search bar () with autocomplete functionality () on my website. The issue I'm facing is that the autocomplete feature seems to affect the display of the search icon. When doing a "select all," it be ...

Creating a simulated callback function using Jest with a promise

I am currently testing a specific function within my component that is triggered only when the API request is successful. To provide some background, this function is called upon clicking a button: return onUpdate(params, setError, success, cancel); Once ...

Jquery UI sortable can determine the vertical orientation, either moving items up or down

I am having difficulty determining the direction in which axis N is moving, whether up or down. I would also like the elements (h2 and p) inside to remain in their positions. Can anyone provide assistance? http://jsfiddle.net/zerolfc/y62awe4u/2/ <div ...

Having trouble grasping ES6 concepts with Reactjs?

I am completely new to reactjs and recently followed a tutorial (link: https://www.youtube.com/watch?v=Ke90Tje7VS0). Currently, I am using Windows and following the commands in cmd as instructed in the tutorial: npm i -g <a href="/cdn-cgi/l/email-prote ...

Avoid having the image display over the text

Recently I began exploring web development. I am in the process of creating a website that fetches data from the mealdb API and showcases it on the site. Most aspects are functioning smoothly, however, there is an issue when inspecting the webpage on mobil ...

Extract the post date/time directly from the HTML code without relying on JavaScript

I encountered an issue while attempting to store the time and date from a form into a variable. An error message indicated that the variable was unknown. Below is the code I used: HTML <div class="form-group"> <label for="dp">Departure Da ...

Function within a while loop

I am attempting to retrieve the content of a specific textarea tag when a particular button is clicked. I believe that using a loop would be helpful in this situation. In PHP, the while loop can be used to dynamically change the name of the textarea and ...

CSS techniques for aligning content

I am currently working on designing a website template, and I have encountered an issue with positioning three individual columns that contain blocks of content. My objective is to have the first block of content in each column start at the top of their re ...

Harnessing the Power of NextJS Image Component and @svgr/webpack for Seamless Integration

I have recently set up a Next.js site utilizing the @svgr/webpack library. In order to start using an SVG image with the new next/image component, I configured my next.config.js file accordingly. My next.config.js setup looks like this: module.exports = { ...

What is the method for assigning a value to a variable in xhr.setRequestHeader?

I'm working on setting a value to the variable in xhr.setRequestHeader(Authentication, "Bearer" + parameter); with xmlhttprequest. Can you provide guidance on how to effectively pass a value to the variable within xhr.setRequestHeader? ...

Which is better for React development: TypeScript, Flow, or another option?

As I dive into learning React, one thing that has been on my mind is the tools developers use for static type checking when building robust React applications. I personally find TypeScript to be a great choice. It eases the process of developing JavaScrip ...

Interacting with a button element specified with the role attribute inside a div container using Selenium

Is there a way to interact with the button using the HTML tag provided below? <div class="_1WZqU PNlAR" role="button">OK</div> I attempted the following methods: driver.findElement(By.xpath("//button[text()='OK']")).click(); driver ...

Resizing the Canvas in Three.js with GLSL

I'm currently facing challenges with maintaining the proportions when resizing the window to smaller sizes on mobile devices as shown in this CodePen. The lines and interaction become difficult to see on mobile screens. Is there a solution to address ...

Press a button to delete an item from the array

I am currently utilizing angularJS for the development of a Single Page Application (SPA). My challenge lies in deleting an object from an array within my controller, particularly while using ng-repeat. Below is the relevant HTML snippet: <div class="c ...

Display only the most recent AJAX results

There are times when I encounter a scenario where performing an action on the page triggers an ajax request. If multiple actions of this nature happen in quick succession, each ajax request performs its task (such as updating a list of items) one after t ...

Implementing dynamic button functionality to toggle classes on click event

Within my interface, I have a series of buttons with the following structure: <button id="btn1" type="button" class="btn btn-default btn-sm margin-left-1"> <span class="glyphicon glyphicon-chevron-down"></span> </butto ...