Re: Proposal: make css clip and clip-path respect containing block

This topic is near and dear to my heart, since I've spent the last three
months of my life laying the necessary groundwork to make this work in
Firefox with compositing and threaded scrolling.

First off, I'd like to mention that the effect of having a scrolled clip on
an unscrolled element is not always unexpected. There are pages that
explicitly want this effect, for example [1], [2], and [3]. These are
simpler cases though, where the clip is just a rectangle.
The former two pages achieve this effect using the "clip" property on a
moving / scrolled element, and nesting a position:fixed element inside that
element. The latter uses JS to achieve the effect; it moves the clip by
updating transforms on fixed overflow:hidden elements from a scroll handler.
The CSS-only variants are obviously preferred because they let the browser
do correct async scrolling without the help of JS to adjust the effect.

The "clip" property is officially deprecated and superseded by clip-path.
MDN even says that it has been removed from the specs. I have not verified
that, but looking at these examples it seems like browsers need to keep
supporting clip anyway, so maybe it should be re-added. If clip-path will
not support the above-mentioned scroll effect, but clip does, it would put
us in an odd situation, and probably cause some confusion for web
developers.

As for implementation complexity: In Firefox, most of the complexity is
already required for supporting clip. We don't support clip-path on the
compositor yet, but we're going to add support for it soon, including
support for async scrolling. (At the moment, clip-path always forces us to
use main-thread painting.)
I don't think our implementation would become noticeable simpler if we
stopped clipping positioned elements. There's only one case that I'm a bit
worried about, and that's the case where you have a scroll frame *inside* a
position:absolute element which is inside a clip-path that is scrolled by a
different scroll frame. In that case, the two scroll frames would be in
different branches of the scroll tree, and one of them would move the clip
of the other scroll frame's contents while the other would move the
contents themselves. But even that case should be reasonably simple to get
working.

Not applying the clip to positioned elements would also make other things
more complicated. The positioned element would need to escape from the
clip-path container display item (using Gecko terminology here). I don't
think this kind of escape hatch is used for any other CSS effects.
I'm also confused about how it work when you add more container effects.
Let's say you have this structure:
<div style="clip-path: ...">
  <div style="opacity: 0.8">
    <div style="position:absolute;">not clipped</div>
    <div>clipped</div>
  </div>
</div>
You'll want the opacity to apply to both the clipped and the unclipped
element here, correct? Will this require individual re-wrapping of the
escaped items into opacity items?

Markus

[1]
http://www.bbc.co.uk/news/resources/idt-248d9ac7-9784-4769-936a-8d3b435857a8
[2] http://dok.sonntagszeitung.ch/2016/ubsinnovation/
[3] http://www.flagofplanetearth.com/

On Fri, Sep 9, 2016 at 1:06 PM, Chris Harrelson <chrishtr@google.com> wrote:

> TL;DR:
>
>  (a) *css clip would no longer clip fixed-position descendants* (these
> are the only descendants that would not respect containing block because
> css clip requires absolute position)
>
>  (b) *clip-path would no longer clip descendants for whom the element
> with clip-path is not on the containing block*. e.g. fixed or
> absolute-position descendants would not be clipped by a clip-path element
> that is not positioned or is relatively positioned.
>
> Details:
>
> Compatibility data for Chrome indicates this could be web-compatible. (a)
> affects fewer than 0.018%
> <https://www.chromestatus.com/metrics/feature/popularity#ClipCssOfPositionedElement>
> of pages, and (b) fewer than 0.0069%
> <https://www.chromestatus.com/metrics/feature/popularity#ClipPathOfPositionedElement>
> (and this is with -webkit-clip-path). Note that the real numbers may be
> significantly lower than this, since the counting counts all positioned
> descendants, not those whose containing block differs.
>
> In addition, while -webkit-clip-path is still prefixed in some browsers
> and not commonly used, we have more opportunity to fix it.
>
> Why:
>
> 1. Causes confusion for developers. For example:
>
>  <div id=scroller style="overflow: scroll">
>   <div id="clip-path" style="clip-path: ...">
>     <div id="descendant" style="position: absolute">
>   </div>
> </div>
>
> "clip-path" will clip "descendant", and is scrolled by "scrolle".
> "descendant" is not scrolled. Thus as a scroll occurs, the "clip-path"
> moves relative to "descendant". This is confusing and not really desirable.
>
> 2. Causes significant complexity for browsers. Chrome's research shows
> that there are many bugs
> <https://docs.google.com/document/d/1LFQ0J_c5RGIJ9g5iOOKQJL96uJZRVUMwQkppyXknI2Y/edit>
> in the implementation of css clip and clip-path in various special cases
> of Chrome's implementation and that of other browsers, especially in paths
> that involve compositing. The bugs are directly due to the weirdness of
> examples like #1 and even more exotic variants, because implementing it
> correctly involves carefully separating out pieces of DOM subtrees that
> need individual compositing and scrolling behavior. This also leads to
> worse performance due to extra composited layers or tree traversals to
> determine correct clipping relationships. In some cases it's not even clear
> it's possible to implement "correctly", i.e. the spec is ill-defined.
>
> These bugs and the resulting code complexity are pure overhead that we can
> get rid of, since as far as I can see, web developers almost certainly
> don't want these exotic cases to behave "according to the current spec".
> The proposal in this email doesn't solve everything with containing block,
> but is a step in the right direction.
>
> Thanks,
> Chris
>

Received on Thursday, 15 September 2016 09:40:20 UTC