Trevor Burnham
Trevor Burnham

Reputation: 77416

How do I get the absolute position of an element within a scrollable area in jQuery?

Let's say that I have a div $container with position: relative, and a div $foo within it with position: absolute. I want to get the position of $foo relative to the container. jQuery makes this easy:

$foo.position()

which returns an object with top and left properties, specified in pixels. The problem is, this number is no longer accurate if the container is scrolled down or to the right at all. Specifically, it changes, when it shouldn't. jQuery computes position() such that it's equivalent to $foo.offset() - $container.offset() (where offset() gives the window-relative position), and $foo.offset() changes as the user scrolls around $container.

Upvotes: 2

Views: 1722

Answers (2)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 195992

Add the .scrollLeft() and .scrollTop() of the $container to the values returned by the .position() of the $foo

That should cover it ..

Update

To find the relative parent you should use the following

var $parent = $foo.parents()
                  .filter(
                       function(){
                            var position =  $(this).css('position')
                            return position==='relative' || position==='absolute';
                                 }
                         ).eq(0);

Upvotes: 0

Trevor Burnham
Trevor Burnham

Reputation: 77416

It seems you need to take $foo.position() and then adjust is by adding $container's scrollTop() and scrollLeft().

This becomes annoying if you don't actually know what $foo's relative container is. I've resorted to writing a function (in CoffeeScript):

$.fn.container: ->
  $parent: @parent()
  if $parent.css('position') is 'relative'
    return $parent
  else
    return $parent.container()

Is there a more direct way that I'm overlooking? Or a direct way of finding an arbitrary element's container's scrollbar positions?

[Update: After reading Gaby's answer and comments, I cooked up a small jQuery plugin that goes through all of an element's parents and adds their scrollTop() and scrollLeft() to that element's position(). I haven't tested this thoroughly, so please try it and let me know if it works for you: jqPositionWithScrolling plugin

It's a little odd that position() doesn't do this automatically—I'd dare call it a bug.]

Upvotes: 1

Related Questions