Ticket #8362 (closed bug: patchwelcome)
postion and offset differing in browers when CSS transforms in use
| Reported by: | moronicbajebus | Owned by: | moronicbajebus |
|---|---|---|---|
| Priority: | low | Milestone: | 1.next |
| Component: | dimensions | Version: | 1.5 |
| Keywords: | standards | Cc: | |
| Blocking: | Blocked by: |
Description
Example: http://jsfiddle.net/8j6AF/1/
When CSS transforms are used with scaling, Gecko and Webkit report differ values for offset and position. They report the same value for the CSS value for left and top.
Firefox appears to report the position before it is transformed.
Webkit appears to report the position after it is transformed.
Change History
comment:1 Changed 2 years ago by jitter
- Keywords browserbug browser-firefox added
- Owner set to moronicbajebus
- Status changed from new to pending
- Component changed from unfiled to dimensions
- Priority changed from undecided to low
comment:2 Changed 2 years ago by dhilowitz@…
FYI: I think it's actually a bug in everything else. I'm pretty sure that element.getBoundingClientRect() (which is the basis for jQuery's offset() function) is supposed to return coordinates before the transform is applied. In other words, you're supposed to be able to continue manipulating objects as though no transform has been applied.
The following offset function does return the right (ie "pre-transform" coordinates):
function getOffset( el ) {
var _x = 0; var _y = 0; while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft; _y += el.offsetTop; el = el.offsetParent;
} return { top: _y, left: _x };
}
comment:3 Changed 2 years ago by MrMamen
Not so sure if this is a firefox bug. At least. trident & presto layout engines seems to work the same way as mozilla, so it is only webkit that does this different.
comment:4 Changed 2 years ago by addyosmani
- Status changed from pending to open
We've discussed this and we think it would be of benefit to first petition vendors to try getting these changes brought into place on their end. We can then standardize as needed.
comment:5 Changed 2 years ago by damiar@…
This affects the jQuery UI Draggable plugin as well. When an element is rotated and is draggable, the element gets displaced a few pixels before the startDrag event is triggered. Debugging, I found out that this is caused by the top and left position returned by webkit (which returns the upper left corner's position of the element whereas Gecko returns the upper left position of the bounding rect box).
A quick test case can be set up by just creating a draggable element and then applying a rotation of 45deg to it. Then you only need to drag the element and you would see that the element moves up a few pixels on the first 'mousemove' event, then the dragging works well.
This guy also realized of this and, if you check the final example, you would see how the images have a little awkward movement when you start to drag them: http://www.elated.com/articles/smooth-rotatable-images-css3-jquery/ (check 'step 10' and the final example)
comment:6 Changed 2 years ago by damiar@…
Here's a quick test case: http://jsfiddle.net/qnxGE/2/ (use webkit)
Check how the helper is rendered with an incorrect initial position.
PLEASE NOTE, that although I'm using jQuery UI in the example this is not a bug in jQuery UI itself as it relies on the information the method offset() returns, I'm only using it because is more easy to provide an example.
comment:9 Changed 23 months ago by crashsmoke
To rectify the problem in draggable use dhilowitz's code to calculate the top and left before transformation: function get_unrotated_left_top(el) {
var _x = 0; var _y = 0; while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
_x += el.offsetLeft; _y += el.offsetTop; el = el.offsetParent;
} return { top: _y, left: _x };
}
Then in _mouseStart: function(event) { see my changes here: The element's absolute position on the page minus margins
AD custom changes start - stop draggable jumping after transformed var pos = get_unrotated_left_top(this.element.get(0)); this.offset = pos; /* orig - start this.offset = this.positionAbs = this.element.offset();
orig - end */
AD custom changes end - stop draggable jumping after transformed this.offset = {
top: this.offset.top - this.margins.top, left: this.offset.left - this.margins.left
};
comment:10 Changed 18 months ago by ecmanaut
http://jsfiddle.net/z3asJ/ is a fork of the original jsfiddle, where I added an evolved version of Firebug's getViewOffset function (1.0.5, IIRC - MIT licensed, used in its node highlighting code), which I have adapted for monkeypatching jQuery UI Draggable 1.8.16 to work right (for details, see http://stackoverflow.com/questions/3523747/webkit-and-jquery-draggable-jumping/8730874#8730874), instead of relying on the not-quite-working offset().
I'd be happy if jQuery adopted this, and even happier if browsers exposed these calculations natively in the DOM, so we don't have to.
comment:11 Changed 14 months ago by chris@…
Just want to add my voice to those noting this isn't a Firefox bug. Maybe tags should be updated? This is a pretty big deal imho
comment:12 Changed 14 months ago by dmethvin
#11114 is a duplicate of this ticket.
comment:13 Changed 14 months ago by dmethvin
- Keywords standards added; browserbug browser-firefox removed
- Status changed from open to closed
- Resolution set to patchwelcome
Per #11114, affects width and height as well. See ecmanaut's comment 10 above for a workaround. There is no way we'd land that much code for a case like this; take that code and turn it into a plugin. In the meantime we'll lobby for the browsers to expose this information rather than us (or you) having to recalculate something they already know.
comment:14 Changed 10 months ago by craig_fitz
I thought jQuery's value proposition was cross-browser compatibility? I'm surprised the official word seems to be to petition vendors to clean up their act. I though this was jQuery's claim to fame, it wrapped the vendor's inconsistencies for us.
comment:15 Changed 10 months ago by dmethvin
#12352 is a duplicate of this ticket.
comment:16 Changed 7 months ago by timmywil
#12887 is a duplicate of this ticket.
Please follow the bug reporting guidlines and use jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

Thanks for taking the time to contribute to the jQuery project by writing a bug report and providing a test case!
After checking your report and test case I fail to see how this is a jQuery issue. To me this looks like a bug in Firefox and thus should be report to them.
Please report back if you can provide information on how this is bug in jQuery or if you know of a way to workaround this. If you happen to file this a bug on the Firefox bug tracker please add the link here too.