jQuery offset top doesn't work correctly
Asked Answered
P

3

18

I'm trying to create an script draw something in an element by mouse and I'm using Raphaeljs to do that.

For correct drawing I need to find top and left of ‍input‍‍ element. I'm using var offset = $("#input").offset(); to get left and top.

But the top value isn't correct. It's 10px lower than ‍‍the real top distance. I think the 10px maybe change in different resolutions then I can't add 10px to it normally then I want to know how can I fix the problem!

I uploaded my test here.

Posterity answered 23/8, 2012 at 8:30 Comment(2)
Have you checked margins or padding on any containing element?Cleliaclellan
@Archer yes. I have and there were no margin or padding!Posterity
H
26

The jQuery .offset() function has this limitation:

Note: jQuery does not support getting the offset coordinates of hidden elements or accounting for borders, margins, or padding set on the body element.

The body in this case has a 10px top border, which is why your drawing is off by 10 pixels.

Recommended solution:

var offset = $("#input").offset();
x = x - offset.left - $(document.body).css( "border-left" );
y = y - offset.top + $(document.body).css( "border-top" );
Howler answered 23/8, 2012 at 18:18 Comment(1)
Just as an addendum to use of the offset() property: I was getting what seemed to be erroneous results from it (I was trying to use offset to find the distance of a navigation list from the top of the viewport, in order to use that value as the 'top offset' setting in bootstrap's 'affix' add-on). What I discovered was that offset was miscalculating the distance unless all of the HTML elements above the list element in question (ie. those that determined its place on the page) had explicitly-declared heights. Giving them specific heights in css solved it.Hanako
M
8

After fighting with this for a while and reviewing various potential answers I have concluded that jQuery offset().top (and presumably DOM API that it uses) is too unreliable for general use. Not only is it documented as excluding html level margins, but it also returns unexpected results in several other cases.

position().top does work, but it may not be practical / possible to design the page so that it is equivalent.

Fortunately I have found that element.getBoundingClientRect().top gets the position relative to the viewport perfectly. You can then add on $(document).scrollTop() to get the position from the top of the document if required.

Meekins answered 29/1, 2018 at 15:51 Comment(0)
I
5

I have two different solutions:

1) You can calculate above element's total height with outerHeight(true) method. This method will calculate height with margins, paddings and borders.

And this won't create conflict, it will return true value. Here is jsFiddle example.

html

<div class="header"></div>
<div class="nav"></div>
<div class="myEle"></div>

jQuery

var myEleTop = $('.header').outerHeight(true) + $('.nav').outerHeight(true);

2) If you defined top css to the element which is postioned relative to the body, you can use this value too:

parseInt($('#myEle').css('top'));
Idyllist answered 23/8, 2012 at 8:44 Comment(8)
I tried it! it just return an exception that says top doesn't exist!Posterity
I tested $("#input").css("top") the result is herePosterity
I added a second way, long but much more solidIdyllist
@ahmadalishafiee What do you mean by maintenance?? You just need to write a function for this, and then leave it as is forever...Disciplinant
@MahdiGhiasi I know what to do. but when I edit the html then I should rewrite the function and it make works hard. remember that you should write codes as good as when you want to give it to a killer who knows your home address to maintenance!!! that's why I say it's hard to maintenance!Posterity
@ahmadalishafiee You can create a global function, which gets the element, and returns the value. It may be not easy, but your code will be clean!Disciplinant
@MahdiGhiasi I thought about that but now I think It's better to make .offset() better to work with margin and paddingPosterity
The comment that I made above regarding the use of 'offset' (getting erroneous results unless the preceding HTML elements have a height explicitly declared in CSS) also applies to the outerHeight technique. I tried both ways, and got dodgy results until I gave specific heights to those HTML elements. Seems a bit odd, but there you go.Hanako

© 2022 - 2024 — McMap. All rights reserved.