Skip to content

[cssom-view] Synthetic click's pageX/Y and offsetX/Y are ambiguous in the spec and incompatibly implemented #8531

@jenseng

Description

@jenseng

This might be more appropriately moved to https://github.com/whatwg/html to clarify this section, but I'm opening it here to start a discussion.

According to CSSOM View, pageX/pageY should return the coordinate of the position where the event occurred relative to the origin of the initial containing block (i.e. document). Similarly, offsetX/offsetY should return the position where the event occurred relative to the origin of the padding edge of the target node.

What's not clear for synthetic pointer events is: what is the position where the event occurred? Based on the clientX/Y defaults of (0, 0), one could infer that the event position is the origin of the viewport, and that is indeed what Chrome does with respect to computing pageX/Y (i.e. they reflect the scroll offset). However:

  1. Webkit and Gecko do not consider the scroll offset when computing pageX/Y (i.e. it's always (0, 0)), so perhaps the event occurred at the origin of the document?
  2. All browsers set the offsetX/Y to (0, 0). At a glance this seems reasonable, but this is actually incompatible with the pageX/Y values above, since all these values are relative to the position where the event occurred. It's a little easier to see the problem visually (each col/row represents one pixel):
    +--------------------+
    | document           |
    |                    |
    |   +---------------+|  scroll offset: (4, 3)
    |   | viewport      ||
    |   |               ||
    |   |     +--------+||  target position relative to document (10, 6)
    |   |     | target |||                  relative to viewport (6, 3)
    |   |     +--------+||
    |   +---------------+|
    +--------------------+
    
    If offsetX/Y = (0, 0) is correct (i.e. the event occurred at the target origin), then pageX/Y should be (10, 6), but that is not the case in any browser.

To resolve these discrepancies, we need to clarify what the position should be for synthetic pointer events. Some options:

  1. Event position = document origin, so pageX/Y should be (0, 0) and offsetX/Y should be the document origin's coordinate relative to the target (e.g. (-10, -6))
  2. Event position = viewport origin, so pageX/Y should reflect the scroll offset (e.g. (4, 3)) and offsetX/Y should be the viewport origin's coordinate relative to the target node (e.g. (-6, -3))
  3. Event position = target node origin, so pageX/Y should reflect the target node's coordinate relative to the document origin (e.g. (10, 6)) and offsetX/Y should be (0, 0).
  4. Event position = 🤷, we make an exception in the CSSOM View spec for synthetic pointer events to set both pageX/Y and offsetX/offsetY to (0, 0). This would match the current behavior in Gecko and Webkit.

IMO option 3 makes the most sense, i.e. it's weird for a "click" on an node to be positioned outside that node. It's also likely that offsetX/Y being (0, 0) is relied on in the wild (either explicitly by developers or implicitly by implementations), e.g. activating an Image Button by hitting enter adds (0, 0) entries to the form data set. Option 4 could work too, but it's a little weird and could be a source of confusion. In either case, offsetX/Y would already be correct across the board, it's "just" a matter of fixing pageX/Y in one or all implementations 😄. Options 1 and 2 seem likely to break websites and I suspect could also be more work to implement, so IMO they aren't worth exploring.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions