views:

546

answers:

3

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.

+3  A: 

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
doesn't work if containing div doesn't align with top of page
cobbal
What do you mean it doesn't work if div doesn't align with the top of the page?
Ryan Lynch
scrolls to the wrong place for me if some text is placed before div #foo
cobbal
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
maybe it's a bug in safari then
cobbal
@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
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
doesn't work here (on safari at least): http://jsbin.com/opane3
cobbal
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
that fixes it (15 chars)
cobbal
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
+1  A: 
$(document).ready(function() {
   $("#foo").scrollTop($("#foo #bar").position().top);
})
happytime harry
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
$('#bar').scrollTop() would give you the scrollTop property bar, which would be 0, which would do nothing.
Ryan Lynch
You're all over it Ryan. Many thanks for pointing out my obvious oversight as this is an extremely complicated question/solution.
happytime harry
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
A: 

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
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
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
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 `<p>` before your `bar` in your test and try your answer to see what I mean.
Ryan Lynch
can't seem to reproduce it, still works fine for me (firefox and safari) if I replace with `<p>content...</p>`. http://jsbin.com/ofaqa
cobbal
Right. So I figured out what was causing all the confusion, check out the final edit to my answer.
Ryan Lynch