Phrogz
Phrogz

Reputation: 303261

What should getBoundingClientRect() return for foreignObject XHTML elements embedded in SVG?

Consider an SVG document like this…

<svg viewBox="0 0 200 200" width="100%" height="100%" …>
  <g transform="rotate(45) skewX(10)">
    <foreignObject x="100" y="200" width="10" …>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p id="foo">Hi Mom!</p>
      </body>
    </foreignObject>
  </g>
</svg>

…and JavaScript code like this…

console.log( document.getElementById('foo').getBoundingClientRect() );

Notice that:

Should getBoundingClientRect() return the left/right/top/bottom of the screen-aligned bounding rectangle in the web browser?

Or should it return the coordinates of the object within the context of the body, and leave it up to the user to transform from the foreignObject space into the screen pixels for the scaled/rotated/skewed SVG?

I'm not so much interested in your opinion of how this should behave as a clear interpretation of how the specifications involved dictate that this shall behave.

Here's a simple example of this, showing that Chrome does the former while Firefox does the latter: http://phrogz.net/SVG/html_location_in_svg_in_html.xhtml

Edit: Here's the Webkit bug describing Chrome/Safari's incorrect handling of this test case: https://bugs.webkit.org/show_bug.cgi?id=71819

Upvotes: 4

Views: 3463

Answers (1)

Phrogz
Phrogz

Reputation: 303261

As noted by Boris Zbarsky in my (incorrect) bug report, the CSSOM View Module spec says:

The getClientRects() and getBoundingClientRect() methods provide information about the position of the border box edges of an element relative to the viewport.

…and the specification elsewhere explicitly defines viewport as:

[...] defined by CSS 2.1 unless there is an ancestor foreignObject element in the http://www.w3.org/2000/svg namespace in which case that element acts as viewport and initial containing block.

In summary, getBoundingClientRect() called on an HTML element inside a <foreignObject> in an <svg> element should return the bounding box of the element within the viewport specifically for the HTML body; it is up to the scripter to transform from this into screen space, if desired.

Upvotes: 2

Related Questions