2

Let's say I have the following page:

<html>
<body>
<div id='foo' style='scroll:auto;height:400px'>
      // content, content, content...
      <div id='bar'></div>
      // content, content, content...
</div>
</body>
</html>

What jQuery (or vanilla Javascript) can I use so that when the page loads, it jumps to #bar only within the div#foo (and not the entire page)? I don't need a fancy animation or scrolling, I just want #bar to be at the top of the div on page load.

Matthew
  • 7,605
  • 7
  • 39
  • 39

3 Answers3

7

jQuery solution (assumes all elements are positioned somehow)

$('#foo').scrollTop($('#bar').position().top);

EDIT

Side note: Make sure you set padding-top on bar and not margin-top if you want to put some space between foo and bar once its scrolled.

EDIT DOM Solution (works whether elements have been positioned or not, see @cobbals answer for a jQuery equivalent):

document.getElementById('foo').scrollTop += document.getElementById('bar').offsetTop - document.getElementById('foo').offsetTop
Ryan Lynch
  • 7,676
  • 1
  • 24
  • 33
  • doesn't work if containing div doesn't align with top of page – cobbal Nov 10 '09 at 15:45
  • What do you mean it doesn't work if div doesn't align with the top of the page? – Ryan Lynch Nov 10 '09 at 15:46
  • scrolls to the wrong place for me if some text is placed before div #foo – cobbal Nov 10 '09 at 15:47
  • All the values being read and set are defined relative to foo as the parent element (`scrollTop()` and `position().top`) so anything outside of foo shouldn't have an effect. – Ryan Lynch Nov 10 '09 at 15:52
  • maybe it's a bug in safari then – cobbal Nov 10 '09 at 15:59
  • @cobbal...check to make sure you closed all your `div` tags when you tested it, and that you are using `$('#bar').position().top` and not `$('#bar').offset().top` – Ryan Lynch Nov 10 '09 at 15:59
  • Ah. that would explain it. I can't test it right now so it would be nice if you could verify that it is correct. – Ryan Lynch Nov 10 '09 at 16:05
  • Huh. For some reason its showing the offset and position both as zero in your test. I'll add a non jQuery solution that should def work. – Ryan Lynch Nov 10 '09 at 16:12
  • Right, so I figured out what the cause of all confusion was. The jQuery solution I first posted depends on `foo` being positioned somehow, either `relative` or `absolute`. The second DOM solution I posted will work regardless of positioning, as long as the `foo` hasn't already been scrolled. I've edited the DOM solution based of @cobbal's jQuery solution to account for the `scrollTop` of `foo` being non-zero. – Ryan Lynch Nov 11 '09 at 00:52
1
$(document).ready(function() {
   $("#foo").scrollTop($("#foo #bar").position().top);
})
mothmonsterman
  • 2,451
  • 3
  • 21
  • 28
  • Nice. Since #bar is an id and you don't technically need to worry about duplicates, the inner contextual selector is unnecessary. Neat to see someone thinking in that direction anyway. – Allain Lalonde Nov 10 '09 at 15:45
  • $('#bar').scrollTop() would give you the scrollTop property bar, which would be 0, which would do nothing. – Ryan Lynch Nov 10 '09 at 16:04
  • You're all over it Ryan. Many thanks for pointing out my obvious oversight as this is an extremely complicated question/solution. – mothmonsterman Nov 10 '09 at 19:13
  • Ha. Sure thing. Check the other solutions and comment threads though because there seems to be an unexpected result when `foo` contains non block elements before `bar`. – Ryan Lynch Nov 11 '09 at 00:26
1

long and unwieldily, there is probably a way to shorten it, but it gets to the right place every time.

$("#foo").scrollTop($("#foo").scrollTop() +
                    $("#bar").offset().top -
                    $("#foo").offset().top);
cobbal
  • 69,903
  • 20
  • 143
  • 156
  • Are you sure? Test it in your page. It runs into the same problem by jQuery solution did when bar has non block elements before it in that `$('#bar').offset().top` returns a different value than `document.getElementById('bar').offsetTop`. – Ryan Lynch Nov 10 '09 at 16:27
  • they do return different values, but `$('#foo').scrollTop() + $("#bar").offset().top` is the same as `document.getElementById('bar').offsetTop` (not exactly sure why, but it seems to work) – cobbal Nov 10 '09 at 16:43
  • Your answer has the opposite problem as my original one. It functions as expected only if `bar` is the first `block` element in `foo`. Put `block` element like a `

    ` before your `bar` in your test and try your answer to see what I mean.

    – Ryan Lynch Nov 10 '09 at 19:16
  • can't seem to reproduce it, still works fine for me (firefox and safari) if I replace with `

    content...

    `. http://jsbin.com/ofaqa
    – cobbal Nov 10 '09 at 19:42
  • Right. So I figured out what was causing all the confusion, check out the final edit to my answer. – Ryan Lynch Nov 11 '09 at 00:49