Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cssom-view] Behavior of MouseEvent.offsetX/Y with inline elements is inconsistent across browsers #5659

Open
noamr opened this issue Oct 23, 2020 · 7 comments

Comments

@noamr
Copy link
Collaborator

noamr commented Oct 23, 2020

See https://drafts.csswg.org/cssom-view/#dom-mouseevent-offsetx
According to the spec, offsetX/offsetY of the MouseEvent should correspond to the target element's padding edge.
However, only Gecko conforms to that when it comes to inline elements.

This makes it so that getting the offsetX for e.g. a elements requires an additional computation, and only on certain browsers, and basically makes offsetX/Y unusable for inline elements.

In the Chromium bug https://bugs.chromium.org/p/chromium/issues/detail?id=1054515#c21 it is stated that web compatibility would be an issue if they decide to change this.

Currently the only way to compute offsetX/Y in a cross-browser way is to use potentially costly measurements such as getClientRects and subtracting them from the event's clientX/clientY.
Some websites do this to avoid the cross-browser complexities.

I suggest one of the following:

  • Fix the issue in Blink/WebKit to match the spec (I am in favor in this, but not too familiar with the web-compat implication)
  • Change the spec and Fix Gecko, maybe create an alternate API to retrieve the offsetX/Y for an inline-element
@chrishtr
Copy link
Contributor

chrishtr commented Nov 3, 2020

Do you have compelling examples for use cases where the specified behavior is better than what Chromium and WebKit happen to do? I'm pretty sure there are some, but examples will help us to distinguish between the two possible courses of action.

Some more points:

  • In terms of minimizing risk to web compatibility, it's pretty clear that changing the spec and Gecko behavior is the safer alternative.
  • Fixing Chromium & WebKit to match the spec might break libraries that work around this inconsistency (and AIUI are used on a lot of sites)
  • If there are strong use cases for the specified behavior, we may be forced to introduce a new offset value for web compatibility anyway
  • I'm guessing that this incompatibility has been around for a very long time? A Chromium bisect shows it has been around since at least M65

@noamr
Copy link
Collaborator Author

noamr commented Nov 3, 2020

Do you have compelling examples for use cases where the specified behavior is better than what Chromium and WebKit happen to do?

Absolutely. mouseenter on a normal link element, returns the offset from the link itself in Firefox, and from the nearest block element (e.g. some grandparent p) in Chrome/Safari. "Nearest block ancestor" is not something that you'd expect from any DOM reading.

Take for example the hover preview popups in wikipedia, the arrow appears close to the actual mouse hover point, relative to the anchor.

@noamr
Copy link
Collaborator Author

noamr commented Nov 3, 2020

  • Fixing Chromium & WebKit to match the spec might break libraries that work around this inconsistency (and AIUI are used on a lot of sites)

I'm not sure if modern libraries try to work around this.

@chrishtr
Copy link
Contributor

chrishtr commented Nov 3, 2020

I'm not sure if modern libraries try to work around this.

I see. You mentioned elsewhere (e.g. here) that this is a common source of layout thrashing. If it isn't common libraries, is it that many sites apply workarounds? Would any of the common workarounds you've seen break if all browsers moved to the currently-specified behavior? If so, do those workarounds use UA sniffing to not do it in Firefox?

@noamr
Copy link
Collaborator Author

noamr commented Nov 3, 2020

The workaround, using event.clientX - getBoundingClientRect().left or other JS measurements synchronously in Javascript, is what can potentially cause layout thrashing, and in general getBoundingClientRect() is a slow function that I've seen in several web-performance gigs.

I don't know about libraries that sniff for Firefox and use offsetX as is, and my research haven't found any.

btw I didn't claim that this issue specifically was a common source of layout thrashing, rather that synchronous measurements can cause layout thrashing, and my hypothesis is that fixing some of these browser compatibility bugs can help reduce use of these synchronous measurement anti-patterns. I did see this several times in practice, including in my current project with wikipedia.

@emilio
Copy link
Collaborator

emilio commented Nov 4, 2020

I think the fact that this interop issue is only related to inline elements diminishes the compat risk quite a bit here, fwiw.

And if Chromium / WebKit can change to be consistent regardless of the display type, that'd be awesome.

@noamr
Copy link
Collaborator Author

noamr commented Nov 12, 2020

I was surprised to find out that MouseEvent.offsetX, according to UseCounter, is used in 50% of websites!

I did some investigation and found that a main contributor to that could be this line in old versions of jQuery. Apparently jQuery copies some of the mouse event props from the native event to the jQuery event, MouseEvent.offsetX being one of them.

So Chrome UseCounter for offsetX/offsetY doesn't check actual usage in this case (and in potential many other cases), but some arbitrary library behavior.

This behavior was fixed in jQuery 7 years ago.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants