Bug Tracker

Opened 12 years ago

Closed 11 years ago

Last modified 9 years ago

#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 jitter

Component: unfileddimensions
Keywords: browserbug browser-firefox added
Owner: set to moronicbajebus
Priority: undecidedlow
Status: newpending

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.

comment:2 Changed 12 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 12 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 12 years ago by addyosmani

Status: pendingopen

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 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 12 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:7 Changed 12 years ago by Timmy Willison

#8969 is a duplicate of this ticket.

comment:8 Changed 12 years ago by Timmy Willison

#9788 is a duplicate of this ticket.

comment:9 Changed 12 years 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 11 years 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 11 years 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 11 years ago by dmethvin

#11114 is a duplicate of this ticket.

comment:13 Changed 11 years ago by dmethvin

Keywords: standards added; browserbug browser-firefox removed
Resolution: patchwelcome
Status: openclosed

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 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 11 years ago by dmethvin

#12352 is a duplicate of this ticket.

comment:16 Changed 11 years ago by Timmy Willison

#12887 is a duplicate of this ticket.

comment:17 Changed 10 years ago by dmethvin

#14056 is a duplicate of this ticket.

comment:18 Changed 10 years ago by mitar

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 mitar

OK, it seems the issue is that width and height do not return width and height after rotation. Position is OK.

comment:20 Changed 10 years ago by dmethvin

#14440 is a duplicate of this ticket.

comment:21 Changed 9 years ago by jimmitjoo@…

Here is a fix of this bug that works.

http://jsbin.com/ojoyuc/4

comment:22 in reply to:  21 Changed 9 years ago by anonymous

Replying to jimmitjoo@…:

Here is a fix of this bug that works.

http://jsbin.com/ojoyuc/4

yes, its working, but when/if the drag-able element is scaled or rotate, but not when parent element is scaled or rotate.

comment:23 Changed 9 years ago by dmethvin

#14640 is a duplicate of this ticket.

comment:24 Changed 9 years ago by 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?

comment:25 in reply to:  24 Changed 9 years ago by moronicbajebus

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.

Note: See TracTickets for help on using tickets.