Hykilpikonna
Hykilpikonna

Reputation: 2161

HTML - How to scroll entire sections without stopping in between?

What I need to accomplish:

My website consists of several sections, with each section occupying an entire page. As the user tries to scrolls down, what I'm trying to accomplish is:

  1. The page does not move at all before the scrolling reaches a certain speed threshold.
  2. Scrolls down an entire page when the scrolling does reach the threshold.

Example websites:


What I tried:

  1. CSS scroll-snap-align: This method only snaps the scrolling after the user stops scrolling.

Sample Code:

<div id="app">
    <section id="page1">Page 1 Content</section>

    <section id="page2">Page 2 Content</section>
</div>
#app
{
    height: 100vh;
}

section
{
    position: relative;
    width: 100%;
    height: 100%;
}

Upvotes: 2

Views: 2417

Answers (2)

Mohammad Hamza Imran
Mohammad Hamza Imran

Reputation: 23

you can give id to the last paragraph and link it somewhere like

<a href="#abrr">hello</a>
<p> long text </p>
<p> another section </p>
<p id="abrr"> last section where we have to go </p>

Upvotes: 0

Prakhar
Prakhar

Reputation: 1485

The first thing that should be noted here is that the scroll event cannot be canceled. Hence it can be only be done by attaching event listener on wheel or mousewheel events (touchmove if touch screen support is also required ).

By using these, I was able to come up with this. The idea here is to maintain a counter, which will increase/decrease its value on every wheel event. If the counter reaches a certain threshold, the scroll function will be triggered. Counter will reset back to 0, N number of miliseconds after stopping the mouse wheel.

Hence in order to trigger the scroll function, the mouse wheel must be turned a certain number of times to reach the threshold within the time limit of N milliseconds.

The drawback in this approach is that the body element is given overflow:hidden property to hide the scrollbar. Otherwise, users will be able to scroll the page without the desired effect. If this is not a problem, then the overflow property can be removed. Also, the touchmove event is not handled in this example but the implementation for that will also be similar.

$(document).ready(function() {

  const COUNTER_THRESHOLD = 5; // Change this to decrease/increase senstivity
  const COUNTER_RESET_DURATION = 400;

  let animating = false;
  let counter = 0;

  function resetDelta() {
    counter = 0
  }
  let deboucncedReset = debounce(resetDelta, COUNTER_RESET_DURATION);

  function handleScroll(event) {
    //event.wheelDelta can be positive or negative based on the direction of scroll
    counter += 1 * (Math.sign(event.wheelDelta));

    //Scroll down if value of counter is negative and absolute value is greater than threshold
    if (!animating && (Math.abs(counter) >= COUNTER_THRESHOLD) && counter < 0) {
      let targetSection = $('section.active').next('section');
      if (targetSection.length) {
        scrollToSection(targetSection);
      }
    }
    //Scroll up if value of counter is positive and absolute value is greater than threshold
    else if (!animating && (Math.abs(counter) >= COUNTER_THRESHOLD) && counter > 0) {
      let targetSection = $('section.active').prev('section');
      if (targetSection.length) {
        scrollToSection(targetSection);
      }
    }
    // prevent default scrolling behaviour of mouse wheel
    event.preventDefault()

    //Reset counter to 0 , 400 miliseconds after stopping the mousewheel
    deboucncedReset()
  }

  function scrollToSection(target) {
    animating = true;
    $('html, body').animate({
      scrollTop: target.offset().top
    }, 800, function() {
      animating = false;
      $('section.active').removeClass('active');
      target.addClass('active');
    });
  }

  function debounce(func, delay) {
    let debounceTimer
    return function() {
      const context = this
      const args = arguments
      clearTimeout(debounceTimer)
      debounceTimer
        = setTimeout(() => func.apply(context, args), delay)
    }
  }


  //Test support for passive listeners
  let supportsPassive = false;
  try {
    let options = Object.defineProperty({}, 'passive', {
      get: function() {
        supportsPassive = true;
      }
    });
    window.addEventListener("testPassive", null, options);
    window.removeEventListener("testPassive", null, options);
  } catch (e) {}

  let wheelOptions = supportsPassive ? {
    passive: false
  } : false;

  // Older browsers used 'mousewheel' event
  let wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

  document.addEventListener(wheelEvent, handleScroll, wheelOptions);

});
body {
  overflow: hidden;
}

#app {
  height: 100vh;
}

section {
  position: relative;
  width: 100%;
  height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="app">

  <section id="page1" class="active">
    <h2>Section 1</h2>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores sequi quaerat officia non sunt sit, assumenda ullam itaque eos natus sed, aliquam adipisci consectetur nemo eum a reprehenderit fuga, ut consequatur beatae tenetur debitis. Officiis,
      quod vitae sapiente tempore odit, quas nemo minus cupiditate laboriosam et cum accusantium porro quam hic soluta? Blanditiis assumenda suscipit accusamus laborum modi, cumque consequatur velit asperiores eius consectetur deserunt fugiat aperiam
      recusandae quibusdam, dolore alias doloribus ut quis, voluptatem dolorum dolores harum unde magni. Commodi ducimus distinctio, quos ipsa, itaque illo nostrum laboriosam corporis sunt ad perferendis laborum ut natus magni dolore unde asperiores!</p>
  </section>

  <section id="page2">
    <h2>Section 2</h2>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Repellendus, consequuntur enim ab dolorem rem, animi voluptates ipsam sequi nisi, dolores quod. Unde molestias facere autem nam error laboriosam eum nisi! Placeat voluptatum voluptate aspernatur.
      Laboriosam nulla eaque culpa corporis consequuntur suscipit temporibus sed, totam, quia sit aut beatae sunt nihil ducimus fugit dolorum inventore minus dolorem modi eius! Aliquid distinctio sed dolorem? Quos ipsum optio fugit asperiores eligendi
      vitae saepe nostrum. Eius minus recusandae quaerat. Fuga inventore temporibus doloremque sequi officia voluptatibus explicabo ad? Distinctio molestiae cupiditate obcaecati eum consequatur, error, illo quidem, maxime expedita veniam assumenda alias
      culpa laudantium!</p>
  </section>
</div>

To make it fully functional, arrow keys and space bar also needs to be handled. But that should be a relatively easy thing to handle.

Upvotes: 3

Related Questions