#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: | |
Blocked by: | Blocking: |
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 (25)
comment:1 Changed 12 years ago by
Component: | unfiled → dimensions |
---|---|
Keywords: | browserbug browser-firefox added |
Owner: | set to moronicbajebus |
Priority: | undecided → low |
Status: | new → pending |
comment:2 Changed 12 years ago by
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 12 years ago by
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 12 years ago by
Status: | pending → 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 12 years ago by
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 12 years ago by
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 12 years ago by
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 11 years ago by
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 11 years ago by
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:13 Changed 11 years ago by
Keywords: | standards added; browserbug browser-firefox removed |
---|---|
Resolution: | → patchwelcome |
Status: | open → closed |
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 11 years ago by
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:18 Changed 10 years ago by
I agree. I thought that the idea of jQuery is to provide an interface which works cross-platform. Not that we have to manually discover that things don't work in some browsers.
I suggest that jQuery provides both functions to get position and size of elements before and after CSS transformations. With all CSS transformations getting more and more popular, jQuery API should be extended to support that as well.
comment:19 Changed 10 years ago by
OK, it seems the issue is that width and height do not return width and height after rotation. Position is OK.
comment:22 Changed 9 years ago by
Replying to jimmitjoo@…:
Here is a fix of this bug that works.
yes, its working, but when/if the drag-able element is scaled or rotate, but not when parent element is scaled or rotate.
comment:24 follow-up: 25 Changed 9 years ago by
Why is this ticket closed while this is obviously still a issue?
Not that it would be performant at all, but how about cloning the element, removing the translation and then checking the offset/position?
comment:25 Changed 9 years ago by
Replying to leongersen@…:
Why is this ticket closed while this is obviously still a issue?
Not that it would be performant at all, but how about cloning the element, removing the translation and then checking the offset/position?
If you test the original test <http://jsfiddle.net/8j6AF/1/>, you'll see that the same thing is reported by all browsers instead of getting different values.
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.