29

So I'm making a website with a lot of Divs that take 100% height. And I want to make a button so when it's clicked to smoothly scroll to next div. I've coded something so when its clicked, it scrolls to specific div.

$(".next").click(function() {
    $('html,body').animate({
        scrollTop: $(".p2").offset().top},
        'slow');
});
body{
  margin: 0;
  height: 100%;
}

.p1{
  height: 100vh;
  width: 70%;
  background-color: #2196F3;
}
.p2{
  height: 100vh;
  width: 70%;
  background-color: #E91E63;
}
.p3{
  height: 100vh;
  width: 70%;
  background-color: #01579B;
}

.admin{
  background-color: #B71C1C;
  height: 100vh;
  position: fixed;
  right: 0%;
  top: 0%;
  width: 30%;
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="p1">
  
</div>
<div class="p2">
  
</div>
<div class="p3">
  
</div>

<div class="admin">
  
  <button class="next">NEXT</button>
  
</div>

4 Answers4

20

To make this work you need to identify the currently displayed div. For that you can apply a class to the element which is currently shown. Then you can use next() to traverse through them all.

Also note in the below example the addition of a common class on all elements, .p, in order to DRY up the CSS and make DOM traversal easier.

$(".next").click(function() {
  var $target = $('.p.active').next('.p');
  if ($target.length == 0)
    $target = $('.p:first');
    
  $('html, body').animate({
    scrollTop: $target.offset().top
  }, 'slow');

  $('.active').removeClass('active');
  $target.addClass('active');
});
body {
  margin: 0;
  height: 100%;
}

.p {
  height: 100vh;
  width: 70%;
}
.p1 {
  background-color: #2196F3;
}
.p2 {
  background-color: #E91E63;
}
.p3 {
  background-color: #01579B;
}

.admin {
  background-color: #B71C1C;
  height: 100vh;
  position: fixed;
  right: 0%;
  top: 0%;
  width: 30%;
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="p p1 active"></div>
<div class="p p2"></div>
<div class="p p3"></div>
<div class="admin">
  <button class="next">NEXT</button>
</div>
Rory McCrossan
  • 306,214
  • 37
  • 269
  • 303
  • If user scroll by hand first, then click button. Is this work to scroll to next div of current showing div ? – thang Feb 27 '19 at 00:20
  • 1
    @thang no, for that you would need to monitor which element is currently shown when the scroll event happens, which you can achieve [like this](https://stackoverflow.com/a/488073/519413) – Rory McCrossan Feb 27 '19 at 08:27
7

Use same class name for container.Start with first element.Each time click target the next scroller element

var f = $('.p1');
var nxt = f;
$(".next").click(function() {

  if (nxt.next('.scroller').length > 0) {
    nxt = nxt.next('.scroller');
  } else {
    nxt = f;
  }
  $('html,body').animate({
      scrollTop: nxt.offset().top
    },
    'slow');
});
body {
  margin: 0;
  height: 100%;
}

.p1 {
  height: 100vh;
  width: 70%;
  background-color: #2196F3;
}

.p2 {
  height: 100vh;
  width: 70%;
  background-color: #E91E63;
}

.p3 {
  height: 100vh;
  width: 70%;
  background-color: #01579B;
}

.admin {
  background-color: #B71C1C;
  height: 100vh;
  position: fixed;
  right: 0%;
  top: 0%;
  width: 30%;
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="p1 scroller">

</div>
<div class="p2 scroller">

</div>
<div class="p3 scroller">

</div>

<div class="admin">

  <button class="next">NEXT</button>

</div>
prasanth
  • 19,775
  • 3
  • 25
  • 48
4

Here is a basic version that moves forward and wraps around to the beginning when it reaches the last slide. We store currSlide outside of the loop and increment the number internally in the function.

For convenience, I added a slide class to each slide which allows me to:

  • easily count the length of the slides
  • condense the CSS

let currSlide = 1;
const SLIDE_LENGTH = $('.slide').length;
$(".next").click(function() {
  currSlide = currSlide === SLIDE_LENGTH ? 1 : ++currSlide;
  $('html,body').animate({
      scrollTop: $(`.p${currSlide}`).offset().top
    },
    'slow');
});
body {
  margin: 0;
  height: 100%;
}

/* Less repetition */
.slide {
  height: 100vh;
  width: 70%;
}

.p1 {
  background-color: #2196F3;
}

.p2 {
  background-color: #E91E63;
}

.p3 {
  background-color: #01579B;
}

.admin {
  background-color: #B71C1C;
  height: 100vh;
  position: fixed;
  right: 0%;
  top: 0%;
  width: 30%;
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slide p1"></div>
<div class="slide p2"></div>
<div class="slide p3"></div>

<div class="admin">
  <button class="next">NEXT</button>
</div>

jsFiddle

Bonus edit:

In case you're interested in adding a previous button at some point…

let currSlide = 1;
const SLIDE_LENGTH = $('.slide').length;

function moveSlide() {
  currSlide = $(this).hasClass("next") ? ++currSlide : --currSlide;
  if (currSlide < 1) {
    currSlide = SLIDE_LENGTH;
  }
  if (currSlide > SLIDE_LENGTH) {
    currSlide = 1;
  }
  $('html,body').animate({
      scrollTop: $(`.p${currSlide}`).offset().top
    },
    'slow');
}

$(".prev, .next").on("click", moveSlide);
body {
  margin: 0;
  height: 100%;
}

/* Less repetition */

.slide {
  height: 100vh;
  width: 70%;
}

.p1 {
  background-color: #2196F3;
}

.p2 {
  background-color: #E91E63;
}

.p3 {
  background-color: #01579B;
}

.admin {
  background-color: #B71C1C;
  height: 100vh;
  position: fixed;
  right: 0%;
  top: 0%;
  width: 30%;
  float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slide p1"></div>
<div class="slide p2"></div>
<div class="slide p3"></div>

<div class="admin">
  <button class="prev">PREVIOUS</button>
  <button class="next">NEXT</button>
</div>

jsFiddle

Andy Hoffman
  • 15,329
  • 3
  • 30
  • 51
0

Since your question asks "How-to in Javascript", I will answer the question in a few lines of vanilla JS:

var p = 1;
const container = document.getElementById('container');
var nextPage = function() {
  var topPos = document.getElementsByClassName('page')[p++].offsetTop;
  container.scrollTo({top: topPos, behavior: 'smooth'});
}

in the above example, page is the class name you assign to your divs you want to scroll to, such as:

<div id="container">
  <div class="page p1"></div>
  <div class="page p2"></div>
  <div class="page p3"></div>
</div>

Since you want to scroll the entire browser window, you just replace

container.scrollTo({top: topPos, behavior: 'smooth'});

with

window.scrollTo({top: topPos, behavior: 'smooth'});

like so:

var p = 1;
var nextPage = function() {
  var topPos = document.getElementsByClassName('page')[p++].offsetTop;
  window.scrollTo({top: topPos, behavior: 'smooth'});
}

You can subtract or add the number of pixels you want to offset the topPos if it's not in the right position

Gregory R.
  • 1,475
  • 1
  • 16
  • 28