views:

981

answers:

4

I am trying to position an span element (let us call it "the tooltip span") relative to a input field. To do this, I am wrapping the tooltip span and the input field in another span element (let's call it "the wrapper span") that has position: relative. Then I set position: absolute on tooltip span. This makes the tooltip span position itself relative to the wrapper span but not being part of the page flow - not taking up any space. This is exactly what I want.

Then, using javascript, I set the position of the tooltip relative to the position of the input element. Since the input element can be shaped differently on different pages (script should be globablly applicable), I am using its offsetTop and offsetLeft properties to calculate its position relative to the wrapper span.

However, I am noticing inconsistencies between browsers here. In Firefox, IE6, 7, 8, it works as expected. But in Chrome and Safari the reported offsetTop seems, well, incorrect.

To prove this, I created the test page below:

<html>
<head>
<style type="text/css">
span { font-size: 8px; position: relative; top: 0; left: 0; border: 1px solid red } 
</style>
</head>
<body>

<span id="wrapper">
<input id="foo" name="foo" type="text">
</span>

<script type="text/javascript">
document.write("<br>Offset parent: " + document.getElementById("foo").offsetParent.id);
document.write("<br>Offset top: " + document.getElementById("foo").offsetTop);
</script>

</body>
</html>

and loaded it in Firefox and Chrome. Both browser report the wrapper span as its offsetParent, but for Firefox the offsetTop is -8 and for Chrome it is 2. Visually the page renders the same in both browsers.

This gives me a headache, because I cannot just hack in a different offset that I always apply when someone is using Chrome, because if I change the font size, the offsetTop will not change, and my script will break.

Is this a bug? Can I solve this differently?

A: 

Put you code into a window.onload function. I recall having issues when attempting to work with the dom directly from a <script> during page load in firefox, and webkit tends to be slightly more willing to give a sane DOM at such points.

This is just based on prior issues i've encountered, i'm not sure if it's applicable to your case.

olliej
+1  A: 

Use jQuery. DOM differences between browsers is one of the things it excels at.

Mike Blandford
Holy rusted metal! I was going to say that this is not one of those problems where JQuery is the answer. But it turns out that there is a position() function I was not aware of, that really does the trick. The question still remains why Chrome/Safari reports the offset differently. But you get the check.
waxwing
A: 

I ran into the same problem, and jQuery's position() function was reporting the same as the offset() function. Ultimately it turns out that even waiting for the document to be ready didn't work for me. I had to check offset() later in the flow (in my case, in my handler that is fired on a window.scroll event).

When I try this test code below, on page load, I get different figures for Firefox + Chrome. Once it loads, however, I can press 'd' and I get the same figure for both browsers.

// this produced different results on Chrome + Firefox (Chrome was wrong!)
$(document).ready(function () {
   var x =  $('#some-div-on-your-page').position().top;
   alert("On load, offset is "+x);   // Chrome + Firefox report diff figures

  $(window).keydown(function(e, r) {
     k = e ? e.keyCode : event.keyCode;
     if(k == 68) {      // press 'd'
        var x =  $('#some-div-on-your-page').position().top;
        alert("Now the offset is "+x); // ...but this is consistent
     }
   });
}

Hope this helps.

Eric
A: 

Hi there, I've been having the same problem as you and I realized that (in my case) the thing that was messing up the offset().top value in chrome, was having one or more images without the "height" attribute above the element.

Before

<img src="/images/foo.jpg" />

offset.top() was 100 in Chrome

offset.top() was 150 in Firefox and IE7 (beleive or not, it worked just fine in IE!)

After

<img src="/images/foo.jpg" height="50" width="50" />

offset.top() is 150 in both Firefox, IE7, AND CHROME.

Notice the the difference was 50px, which is actually the same as the image height.

Since I was developing a JQuery plugin, i tryed to collect all the images that had their width and height attributes undefined, and manually setting their size with .width() and .height(), but it didn't work, because Chrome returned 0 for both functions. So, i guess the problem with offset.top() actually relies on that. If JQuery is triying to get te offset.top() value by accumulating the "above" element's height, and one of those elements it's an image with no specified height, "0" will be added to that sum, and therefore the top value will be missing those "ignored" heights.

PS: Sorry for my english, it's been a long time since i wrote such a long text in this language!

Nicolas