[webcomponents] Adjusting offsetParent, offsetTop, offsetLeft properties in Shadow DOM

Summary: I think the Shadow DOM spec should specify how offset* properties
are handled around shadows. Further, I think "traversable" and
"non-traversable" shadows should be handled uniformly. The offsetParent
property should return the first offsetParent at the same level of shadow
as the receiver, or the document, to maintain lower-boundary encapsulation.
And the offset{Top, Left} properties should be accumulated across "skipped"
offsetParents.

Problem:

It seems the consensus is that there will be two kinds of shadows, ones
that are exposed to the page through properties such as
HTMLElement.shadowRoot, and ones that aren't [1]. The language is emerging
but for now I will refer to these as "traversable" and "non-traversable"
shadows respectively.

In both cases, there's a question of how to handle HTMLElement.offset*
 properties, particularly offsetParent. [2]

Let's talk about a specific example:

<div id="a">
  <div id="b">

{#a's ShadowRoot}
  <div id="c" style="position: relative; left: 10px;">
    <div id="d">
      <content>

In this case, the positioned ancestor of #b is #c. What should the result
of b.offsetParent be?

If the ShadowRoot is "not traversable" it is clear that b.offsetParent
should NOT be c. If it were, it would be very difficult to use
not-traversable shadows that don't accidentally leak an internal node.
(Especially when you consider that c could be a pseudo-element, and the
author could set position: relative on the element that way.)

Discussion:

I think the offset{Parent, Top, Left} properties should be adjusted. This
means that in the above example, b.offsetParent would be <body> and
b.offsetLeft would be silently adjusted to accumulate an offset of 10px
from c. I think this makes sense because typical uses of offsetParent and
offsetLeft, etc. are used to calculate the position of one element in the
coordinate space of another element, and adjusting these properties to work
this way will mean code that naively implements this use case will continue
to work.

This behavior is unfortunately slightly lossy: If the author had #c and
wanted to calculate the position of #b in the coordinate space of #c, they
will need to do some calculation to work it out "via" body. But presumably
a script of this nature is aware of the existence of Shadow DOM.

The question of what to do for offset* properties across a shadow boundary
when the shadow *is* traversable is a vexing one. In this case there is no
node disclosed that you could not find anyway using .shadowRoot, etc. tree
walking. From that point of view it seems acceptable for offsetParent to
return an offsetParent inside the (traversable) shadow.

On the other hand, this violates the lower-boundary encapsulation of the
Shadow DOM spec. This means that pages that are using traversable shadows,
but relying on convention (ie "don't use new properties like .shadowRoot")
to get the encapsulation benefits of Shadow DOM, now have to audit the
offsetParent property. It also means you need to have two ways of dealing
with offsetParent in both user agents and author scripts. So for simplicity
and consistency I think it makes sense to treat both traversable and
non-traversable shadows uniformly.

Dominic

[1] Thread starts here: <
http://lists.w3.org/Archives/Public/public-webapps/2013JanMar/0535.html>
[2] <http://www.w3.org/TR/cssom-view/#offset-attributes>


<http://goto.google.com/dc-email-sla>

Received on Monday, 18 March 2013 08:49:01 UTC