11

On my webpage I have an overflowed div (i.e. with the vertical scrollbar). Inside the div, I have anchors with ids. When I put one of these ids in the URL (mypage.html#id), I want the div, not the page, to scroll to that anchor.

How do I do that, preferably with plain JavaScript? If it's too complex, I'll go with jQuery, but I'm not using it in this project for anything else.

Martin Jespersen
  • 25,743
  • 8
  • 56
  • 68
user323094
  • 3,643
  • 4
  • 21
  • 30

4 Answers4

9
$('.overflow').scrollTop($('#anchor').offset().top);

There is no reason at all you can't convert this to standard javascript.

Note that the scroll will be off if there is a margin on the anchor element.

Ariel
  • 25,995
  • 5
  • 59
  • 69
  • I had to reorganize my HTML and CSS a bit but this works (with .position(), not .offset()). I looked at jQuery source and ripping these methods out might be a bit difficult. I'll try and post pure javascript if I'll succeed. – user323094 Sep 22 '11 at 11:04
  • There are too many interdependencies in jQuery to rip this out. What the hell, I'll go with this solution - I just realized that for the next feature I'd be using jQuery anyway. Thanks for the answer. – user323094 Sep 22 '11 at 12:15
  • Actually, I'll go with the simpler solution with focus(), just tested it. – user323094 Sep 22 '11 at 12:21
  • I was not expecting you to actually rewrite JQuery. Those properties I used are standard javascript ones. Just lookup how to change and read the offset and position, and do it directly. (They have different names sometimes in different browsers.) – Ariel Sep 22 '11 at 13:10
  • 1
    This is a very poor solution that works only when a multitude of extra assumptions are met. Margins, paddings, elements with position: relative in the parent-child hierarchy between the anchor and the div - most combinations of these will break this method. The only reliable way is to compute **document-absolute** vertical positions of the div and the anchor and set scrollTop to their difference. Reliably computing document-absolute positions is **fantastically hard**. Plugins that handle this tend to check DOZENS of special cases for EACH parent-child pair on path from to the element. – Szczepan Hołyszewski Feb 22 '16 at 06:39
5

Have you tried to set focus() on the anchor?

Any DOM element with a tabindex is focusable, and any element which has focus will be scrolled into view by the browser.

Martin Jespersen
  • 25,743
  • 8
  • 56
  • 68
4

This is a pure Javascript (ECMA 6) solution, similar to Ariel's answer.

const overflow = document.querySelector('.overflow');
const anchor = document.getElementById('anchor');

// Get the bounding client rectangles for both
// the overflow container and the target anchor
const rectOverflow = overflow.getBoundingClientRect();
const rectAnchor = anchor.getBoundingClientRect();

// Set the scroll position of the overflow container
overflow.scrollTop = rectAnchor.top - rectOverflow.top;
Caleb
  • 2,268
  • 2
  • 14
  • 16
1

For those of you in nearly any major browser in 2021, use element.scrollIntoView().

https://developer.mozilla.org/docs/Web/API/Element/scrollIntoView

The Element interface's scrollIntoView() method scrolls the element's parent container such that the element on which scrollIntoView() is called is visible to the user - MDN Web Docs

Example:

var myEl = document.getElementById("child");
myEl.scrollIntoView()

or with Parameters -- Not supported in Safari or Internet Explorer:

myEl.scrollIntoView({
    block: "center" // Start, center, end, or nearest. Defaults to start.
    behavior: "smooth"
})
itsisaac19
  • 536
  • 3
  • 15