[javascript] JavaScript to scroll long page to DIV

I have a link on a long HTML page. When I click it, I wish a div on another part of the page to be visible in the window by scrolling into view.

A bit like EnsureVisible in other languages.

I've checked out scrollTop and scrollTo but they seem like red herrings.

Can anyone help?

This question is related to javascript html

The answer is


The difficulty with scrolling is that you may not only need to scroll the page to show a div, but you may need to scroll inside scrollable divs on any number of levels as well.

The scrollTop property is a available on any DOM element, including the document body. By setting it, you can control how far down something is scrolled. You can also use clientHeight and scrollHeight properties to see how much scrolling is needed (scrolling is possible when clientHeight (viewport) is less than scrollHeight (the height of the content).

You can also use the offsetTop property to figure out where in the container an element is located.

To build a truly general purpose "scroll into view" routine from scratch, you would need to start at the node you want to expose, make sure it's in the visible portion of it's parent, then repeat the same for the parent, etc, all the way until you reach the top.

One step of this would look something like this (untested code, not checking edge cases):

function scrollIntoView(node) {
  var parent = node.parent;
  var parentCHeight = parent.clientHeight;
  var parentSHeight = parent.scrollHeight;
  if (parentSHeight > parentCHeight) {
    var nodeHeight = node.clientHeight;
    var nodeOffset = node.offsetTop;
    var scrollOffset = nodeOffset + (nodeHeight / 2) - (parentCHeight / 2);
    parent.scrollTop = scrollOffset;
  }
  if (parent.parent) {
    scrollIntoView(parent);
  }
}

<a href="#myAnchorALongWayDownThePage">Click here to scroll</a>

<A name='myAnchorALongWayDownThePage"></a>

No fancy scrolling but it should take you there.


If you don't want to add an extra extension the following code should work with jQuery.

$('a[href=#target]').
    click(function(){
        var target = $('a[name=target]');
        if (target.length)
        {
            var top = target.offset().top;
            $('html,body').animate({scrollTop: top}, 1000);
            return false;
        }
    });

scrollTop (IIRC) is where in the document the top of the page is scrolled to. scrollTo scrolls the page so that the top of the page is where you specify.

What you need here is some Javascript manipulated styles. Say if you wanted the div off-screen and scroll in from the right you would set the left attribute of the div to the width of the page and then decrease it by a set amount every few seconds until it is where you want.

This should point you in the right direction.

Additional: I'm sorry, I thought you wanted a separate div to 'pop out' from somewhere (sort of like this site does sometimes), and not move the entire page to a section. Proper use of anchors would achieve that effect.


There is a jQuery plugin for the general case of scrolling to a DOM element, but if performance is an issue (and when is it not?), I would suggest doing it manually. This involves two steps:

  1. Finding the position of the element you are scrolling to.
  2. Scrolling to that position.

quirksmode gives a good explanation of the mechanism behind the former. Here's my preferred solution:

function absoluteOffset(elem) {
    return elem.offsetParent && elem.offsetTop + absoluteOffset(elem.offsetParent);
}

It uses casting from null to 0, which isn't proper etiquette in some circles, but I like it :) The second part uses window.scroll. So the rest of the solution is:

function scrollToElement(elem) {
    window.scroll(absoluteOffset(elem));
}

Voila!


The property you need is location.hash. For example:

location.hash = 'top'; //would jump to named anchor "top

I don't know how to do the nice scroll animation without the use of dojo or some toolkit like that, but if you just need it to jump to an anchor, location.hash should do it.

(tested on FF3 and Safari 3.1.2)


The difficulty with scrolling is that you may not only need to scroll the page to show a div, but you may need to scroll inside scrollable divs on any number of levels as well.

The scrollTop property is a available on any DOM element, including the document body. By setting it, you can control how far down something is scrolled. You can also use clientHeight and scrollHeight properties to see how much scrolling is needed (scrolling is possible when clientHeight (viewport) is less than scrollHeight (the height of the content).

You can also use the offsetTop property to figure out where in the container an element is located.

To build a truly general purpose "scroll into view" routine from scratch, you would need to start at the node you want to expose, make sure it's in the visible portion of it's parent, then repeat the same for the parent, etc, all the way until you reach the top.

One step of this would look something like this (untested code, not checking edge cases):

function scrollIntoView(node) {
  var parent = node.parent;
  var parentCHeight = parent.clientHeight;
  var parentSHeight = parent.scrollHeight;
  if (parentSHeight > parentCHeight) {
    var nodeHeight = node.clientHeight;
    var nodeOffset = node.offsetTop;
    var scrollOffset = nodeOffset + (nodeHeight / 2) - (parentCHeight / 2);
    parent.scrollTop = scrollOffset;
  }
  if (parent.parent) {
    scrollIntoView(parent);
  }
}

Why not a named anchor?



Correct me if I'm wrong but I'm reading the question again and again and still think that Angus McCoteup was asking how to set an element to be position: fixed.

Angus McCoteup, check out http://www.cssplay.co.uk/layouts/fixed.html - if you want your DIV to behave like a menu there, have a look at a CSS there


scrollTop (IIRC) is where in the document the top of the page is scrolled to. scrollTo scrolls the page so that the top of the page is where you specify.

What you need here is some Javascript manipulated styles. Say if you wanted the div off-screen and scroll in from the right you would set the left attribute of the div to the width of the page and then decrease it by a set amount every few seconds until it is where you want.

This should point you in the right direction.

Additional: I'm sorry, I thought you wanted a separate div to 'pop out' from somewhere (sort of like this site does sometimes), and not move the entire page to a section. Proper use of anchors would achieve that effect.


old question, but if anyone finds this through google (as I did) and who does not want to use anchors or jquery; there's a builtin javascriptfunction to 'jump' to an element;

document.getElementById('youridhere').scrollIntoView();

and what's even better; according to the great compatibility-tables on quirksmode, this is supported by all major browsers!


Why not a named anchor?


You can use Element.scrollIntoView() method as was mentioned above. If you leave it with no parameters inside you will have an instant ugly scroll. To prevent that you can add this parameter - behavior:"smooth".

Example:

document.getElementById('scroll-here-plz').scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});

Just replace scroll-here-plz with your div or element on a website. And if you see your element at the bottom of your window or the position is not what you would have expected, play with parameter block: "". You can use block: "start", block: "end" or block: "center".

Remember: Always use parameters inside an object {}.

If you would still have problems, go to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

There is detailed documentation for this method.


I personally found Josh's jQuery-based answer above to be the best I saw, and worked perfectly for my application... of course, I was already using jQuery... I certainly wouldn't have included the whole jQ library just for that one purpose.

Cheers!

EDIT: OK... so mere seconds after posting this, I saw another answer just below mine (not sure if still below me after an edit) that said to use:

document.getElementById('your_element_ID_here').scrollIntoView();

This works perfectly and in so much less code than the jQuery version! I had no idea that there was a built-in function in JS called .scrollIntoView(), but there it is! So, if you want the fancy animation, go jQuery. Quick n' dirty... use this one!


There is a jQuery plugin for the general case of scrolling to a DOM element, but if performance is an issue (and when is it not?), I would suggest doing it manually. This involves two steps:

  1. Finding the position of the element you are scrolling to.
  2. Scrolling to that position.

quirksmode gives a good explanation of the mechanism behind the former. Here's my preferred solution:

function absoluteOffset(elem) {
    return elem.offsetParent && elem.offsetTop + absoluteOffset(elem.offsetParent);
}

It uses casting from null to 0, which isn't proper etiquette in some circles, but I like it :) The second part uses window.scroll. So the rest of the solution is:

function scrollToElement(elem) {
    window.scroll(absoluteOffset(elem));
}

Voila!


old question, but if anyone finds this through google (as I did) and who does not want to use anchors or jquery; there's a builtin javascriptfunction to 'jump' to an element;

document.getElementById('youridhere').scrollIntoView();

and what's even better; according to the great compatibility-tables on quirksmode, this is supported by all major browsers!


The property you need is location.hash. For example:

location.hash = 'top'; //would jump to named anchor "top

I don't know how to do the nice scroll animation without the use of dojo or some toolkit like that, but if you just need it to jump to an anchor, location.hash should do it.

(tested on FF3 and Safari 3.1.2)


There is a jQuery plugin for the general case of scrolling to a DOM element, but if performance is an issue (and when is it not?), I would suggest doing it manually. This involves two steps:

  1. Finding the position of the element you are scrolling to.
  2. Scrolling to that position.

quirksmode gives a good explanation of the mechanism behind the former. Here's my preferred solution:

function absoluteOffset(elem) {
    return elem.offsetParent && elem.offsetTop + absoluteOffset(elem.offsetParent);
}

It uses casting from null to 0, which isn't proper etiquette in some circles, but I like it :) The second part uses window.scroll. So the rest of the solution is:

function scrollToElement(elem) {
    window.scroll(absoluteOffset(elem));
}

Voila!


Answer posted here - same solution to your problem.

Edit: the JQuery answer is very nice if you want a smooth scroll - I hadn't seen that in action before.


I personally found Josh's jQuery-based answer above to be the best I saw, and worked perfectly for my application... of course, I was already using jQuery... I certainly wouldn't have included the whole jQ library just for that one purpose.

Cheers!

EDIT: OK... so mere seconds after posting this, I saw another answer just below mine (not sure if still below me after an edit) that said to use:

document.getElementById('your_element_ID_here').scrollIntoView();

This works perfectly and in so much less code than the jQuery version! I had no idea that there was a built-in function in JS called .scrollIntoView(), but there it is! So, if you want the fancy animation, go jQuery. Quick n' dirty... use this one!


This worked for me

document.getElementById('divElem').scrollIntoView();

If you don't want to add an extra extension the following code should work with jQuery.

$('a[href=#target]').
    click(function(){
        var target = $('a[name=target]');
        if (target.length)
        {
            var top = target.offset().top;
            $('html,body').animate({scrollTop: top}, 1000);
            return false;
        }
    });

You can use Element.scrollIntoView() method as was mentioned above. If you leave it with no parameters inside you will have an instant ugly scroll. To prevent that you can add this parameter - behavior:"smooth".

Example:

document.getElementById('scroll-here-plz').scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});

Just replace scroll-here-plz with your div or element on a website. And if you see your element at the bottom of your window or the position is not what you would have expected, play with parameter block: "". You can use block: "start", block: "end" or block: "center".

Remember: Always use parameters inside an object {}.

If you would still have problems, go to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

There is detailed documentation for this method.



I can't add a comment to futtta's reply above, but for a smoother scroll use:

onClick="document.getElementById('more').scrollIntoView({block: 'start', behavior: 'smooth'});"

Correct me if I'm wrong but I'm reading the question again and again and still think that Angus McCoteup was asking how to set an element to be position: fixed.

Angus McCoteup, check out http://www.cssplay.co.uk/layouts/fixed.html - if you want your DIV to behave like a menu there, have a look at a CSS there


The difficulty with scrolling is that you may not only need to scroll the page to show a div, but you may need to scroll inside scrollable divs on any number of levels as well.

The scrollTop property is a available on any DOM element, including the document body. By setting it, you can control how far down something is scrolled. You can also use clientHeight and scrollHeight properties to see how much scrolling is needed (scrolling is possible when clientHeight (viewport) is less than scrollHeight (the height of the content).

You can also use the offsetTop property to figure out where in the container an element is located.

To build a truly general purpose "scroll into view" routine from scratch, you would need to start at the node you want to expose, make sure it's in the visible portion of it's parent, then repeat the same for the parent, etc, all the way until you reach the top.

One step of this would look something like this (untested code, not checking edge cases):

function scrollIntoView(node) {
  var parent = node.parent;
  var parentCHeight = parent.clientHeight;
  var parentSHeight = parent.scrollHeight;
  if (parentSHeight > parentCHeight) {
    var nodeHeight = node.clientHeight;
    var nodeOffset = node.offsetTop;
    var scrollOffset = nodeOffset + (nodeHeight / 2) - (parentCHeight / 2);
    parent.scrollTop = scrollOffset;
  }
  if (parent.parent) {
    scrollIntoView(parent);
  }
}

For smooth scroll this code is useful

$('a[href*=#scrollToDivId]').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      var head_height = $('.header').outerHeight(); // if page has any sticky header get the header height else use 0 here
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top - head_height
        }, 1000);
        return false;
      }
    }
  });

<a href="#myAnchorALongWayDownThePage">Click here to scroll</a>

<A name='myAnchorALongWayDownThePage"></a>

No fancy scrolling but it should take you there.


scrollTop (IIRC) is where in the document the top of the page is scrolled to. scrollTo scrolls the page so that the top of the page is where you specify.

What you need here is some Javascript manipulated styles. Say if you wanted the div off-screen and scroll in from the right you would set the left attribute of the div to the width of the page and then decrease it by a set amount every few seconds until it is where you want.

This should point you in the right direction.

Additional: I'm sorry, I thought you wanted a separate div to 'pop out' from somewhere (sort of like this site does sometimes), and not move the entire page to a section. Proper use of anchors would achieve that effect.



scrollTop (IIRC) is where in the document the top of the page is scrolled to. scrollTo scrolls the page so that the top of the page is where you specify.

What you need here is some Javascript manipulated styles. Say if you wanted the div off-screen and scroll in from the right you would set the left attribute of the div to the width of the page and then decrease it by a set amount every few seconds until it is where you want.

This should point you in the right direction.

Additional: I'm sorry, I thought you wanted a separate div to 'pop out' from somewhere (sort of like this site does sometimes), and not move the entire page to a section. Proper use of anchors would achieve that effect.


<a href="#myAnchorALongWayDownThePage">Click here to scroll</a>

<A name='myAnchorALongWayDownThePage"></a>

No fancy scrolling but it should take you there.


I can't add a comment to futtta's reply above, but for a smoother scroll use:

onClick="document.getElementById('more').scrollIntoView({block: 'start', behavior: 'smooth'});"

Correct me if I'm wrong but I'm reading the question again and again and still think that Angus McCoteup was asking how to set an element to be position: fixed.

Angus McCoteup, check out http://www.cssplay.co.uk/layouts/fixed.html - if you want your DIV to behave like a menu there, have a look at a CSS there


Answer posted here - same solution to your problem.

Edit: the JQuery answer is very nice if you want a smooth scroll - I hadn't seen that in action before.


There is a jQuery plugin for the general case of scrolling to a DOM element, but if performance is an issue (and when is it not?), I would suggest doing it manually. This involves two steps:

  1. Finding the position of the element you are scrolling to.
  2. Scrolling to that position.

quirksmode gives a good explanation of the mechanism behind the former. Here's my preferred solution:

function absoluteOffset(elem) {
    return elem.offsetParent && elem.offsetTop + absoluteOffset(elem.offsetParent);
}

It uses casting from null to 0, which isn't proper etiquette in some circles, but I like it :) The second part uses window.scroll. So the rest of the solution is:

function scrollToElement(elem) {
    window.scroll(absoluteOffset(elem));
}

Voila!


If you don't want to add an extra extension the following code should work with jQuery.

$('a[href=#target]').
    click(function(){
        var target = $('a[name=target]');
        if (target.length)
        {
            var top = target.offset().top;
            $('html,body').animate({scrollTop: top}, 1000);
            return false;
        }
    });

Answer posted here - same solution to your problem.

Edit: the JQuery answer is very nice if you want a smooth scroll - I hadn't seen that in action before.


Correct me if I'm wrong but I'm reading the question again and again and still think that Angus McCoteup was asking how to set an element to be position: fixed.

Angus McCoteup, check out http://www.cssplay.co.uk/layouts/fixed.html - if you want your DIV to behave like a menu there, have a look at a CSS there


The difficulty with scrolling is that you may not only need to scroll the page to show a div, but you may need to scroll inside scrollable divs on any number of levels as well.

The scrollTop property is a available on any DOM element, including the document body. By setting it, you can control how far down something is scrolled. You can also use clientHeight and scrollHeight properties to see how much scrolling is needed (scrolling is possible when clientHeight (viewport) is less than scrollHeight (the height of the content).

You can also use the offsetTop property to figure out where in the container an element is located.

To build a truly general purpose "scroll into view" routine from scratch, you would need to start at the node you want to expose, make sure it's in the visible portion of it's parent, then repeat the same for the parent, etc, all the way until you reach the top.

One step of this would look something like this (untested code, not checking edge cases):

function scrollIntoView(node) {
  var parent = node.parent;
  var parentCHeight = parent.clientHeight;
  var parentSHeight = parent.scrollHeight;
  if (parentSHeight > parentCHeight) {
    var nodeHeight = node.clientHeight;
    var nodeOffset = node.offsetTop;
    var scrollOffset = nodeOffset + (nodeHeight / 2) - (parentCHeight / 2);
    parent.scrollTop = scrollOffset;
  }
  if (parent.parent) {
    scrollIntoView(parent);
  }
}

Why not a named anchor?


The property you need is location.hash. For example:

location.hash = 'top'; //would jump to named anchor "top

I don't know how to do the nice scroll animation without the use of dojo or some toolkit like that, but if you just need it to jump to an anchor, location.hash should do it.

(tested on FF3 and Safari 3.1.2)


For smooth scroll this code is useful

$('a[href*=#scrollToDivId]').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      var head_height = $('.header').outerHeight(); // if page has any sticky header get the header height else use 0 here
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top - head_height
        }, 1000);
        return false;
      }
    }
  });

<a href="#myAnchorALongWayDownThePage">Click here to scroll</a>

<A name='myAnchorALongWayDownThePage"></a>

No fancy scrolling but it should take you there.


Answer posted here - same solution to your problem.

Edit: the JQuery answer is very nice if you want a smooth scroll - I hadn't seen that in action before.


This worked for me

document.getElementById('divElem').scrollIntoView();

If you don't want to add an extra extension the following code should work with jQuery.

$('a[href=#target]').
    click(function(){
        var target = $('a[name=target]');
        if (target.length)
        {
            var top = target.offset().top;
            $('html,body').animate({scrollTop: top}, 1000);
            return false;
        }
    });

The property you need is location.hash. For example:

location.hash = 'top'; //would jump to named anchor "top

I don't know how to do the nice scroll animation without the use of dojo or some toolkit like that, but if you just need it to jump to an anchor, location.hash should do it.

(tested on FF3 and Safari 3.1.2)