css transform and transition break hidden overflow on border-radius

6,415 views
Skip to first unread message

sanjo...@samsung.com

unread,
Jun 18, 2013, 7:05:48 AM6/18/13
to graphi...@chromium.org
<style>
.outer {
overflow: hidden;
width: 100px;
height: 100px;
background-color: rgb(0,238,228);
border: 3px solid #000;
border-radius: 50%;
}
.inner {
height: 100%;
line-height: 5.8;
text-align: center;
background-color: rgba(255,0,0,.5);
}
.transform {
-webkit-transform: translate3d(10px,10px,0);
transform: translate3d(10px,10px,0);
}
</style>
<html>
<div class=outer>
<div class="inner transform">with transformdfdfdsfdsf</div>
</div>
</html>

While debugging crbug.com/157218 with the above html, <div class="inner transform"> is promoted to posZOrderList of <html> and gets a compositing layer. So, <html> also gets a compositing layer because of subtree reasons CompositingReasonClipsCompositingDescendants(as <div class="inner transform"> becomes child of <html> in pain-order). So, clippedByAncestor(RenderLayer* layer) for <div class="inner transform"> returns <html> element which is wrong. It should return <div class=outer> as clipping ancestor.

As per my understanding, <div class="inner transform"> should be child of <div class=outer> in paint-order and <div class=outer> should also get a compositing layer and so that clipping works properly.

Please correct me if my understanding is wrong.

Alok Priyadarshi

unread,
Jun 18, 2013, 12:50:32 PM6/18/13
to sanjo...@samsung.com, graphi...@chromium.org
Coincidentally I ran into the same problem while working on another
issue related to canvas: http://crbug.com/236982

Even if you force the "outer" div to be composited by adding a
translateZ(0) property, you will notice that the "inner" div is still
not clipped. I think the main issue here is that hw-composited layers
are not clipped by parent layers.

Shawn Singh

unread,
Jun 19, 2013, 12:41:33 AM6/19/13
to Alok Priyadarshi, sanjo...@samsung.com, graphics-dev
An update - Alok and I had discussed this offline a few times today:

Composited layers are actually recognizing the clipping situation, but round borders on a clip are not supported by the compositor.  It's not clear whether the compositor needs to or should support them, for the long-term solution.

For now, at least, our current thought is to fix this by using a mask layer associated with the border-radius element.  This should allow us to "stencil out" the round corners.  The tradeoff is that this will cause us to create render surfaces for any elements that are (a) composited, (b) have overflow: hidden|scroll, and (c) have a border-radius.  I'm not sure how common this combination is, or how painful it will be to cause such cases to use render surfaces.  It's possible that compositing overflow-scroll divs may increase the occurrence of this scenario, though.

sanjoy pal

unread,
Jun 19, 2013, 5:04:24 AM6/19/13
to graphi...@chromium.org, Alok Priyadarshi, sanjo...@samsung.com, shawn...@google.com
Ok, round borders on a clip are not supported by the compositor.

But, for the below html without border-radius, nothing is getting clipped. But if we force the "outer" div to be composited by adding a 
translateZ(0) property, then its getting clipped. Does that mean the elements with overflow: hidden need to be composited?

<style>
.outer {
    overflow: hidden;
    width: 100px;
    height: 100px;
    background-color: rgb(0,238,228);
    border: 3px solid #000;
    /*border-radius: 50%;*/
}
.inner {
    height: 200px;
    position: absolute;
    line-height: 5.8;
    text-align: center;
    background-color: rgba(255,0,0,.5);
}
.transform {
    -webkit-transform: translate3d(10px,10px,0);
    transform: translate3d(10px,10px,0);
}
</style>
<html>
<div class=outer>
    <div class="inner transform">with transformdfdfdsfdsf</div>
</div>
</html>



Alok Priyadarshi

unread,
Jun 19, 2013, 12:34:41 PM6/19/13
to sanjoy pal, graphi...@chromium.org, sanjo...@samsung.com, Shawn Singh
This may or may not be a bug. I get identical results in Firefox. I
noticed that there are two changes that make the inner div to be
clipped:
1. make the outer div composited by adding a translateZ(0) property.
2. remove the "position: absolute" from the inner div

There may be a CSS rule that explains this behavior.

PhistucK

unread,
Jun 21, 2013, 4:18:27 AM6/21/13
to Alok Priyadarshi, sanjoy pal, Graphics-dev, sanjo...@samsung.com, Shawn Singh
I would doubt it is a feature... this really looks like a bug. I thought overflow: hidden is supposed to wrap everything it contains and hide whatever overflows.


PhistucK

Shawn Singh

unread,
Jun 21, 2013, 2:33:46 PM6/21/13
to PhistucK, Alok Priyadarshi, sanjoy pal, Graphics-dev, sanjo...@samsung.com
Sanjoy's example is actually working as intended. It's CSS spec
that's a little unintuitive here. It is actually possible for
descendant elements of an overflow to not be clipped by the overflow.
Quote from the css 2.1 spec: "Overflow affects the clipping of all of
the element's content except any descendant elements (and their
respective content and descendants) whose containing block is the
viewport or an ancestor of the element." That quote is from
http://www.w3.org/TR/CSS21/visufx.html#overflow

The term "containing block" is also carefully defined by CSS, and it's
a little tricky. The example Sanjoy is giving is falling under this
special case where the containing block is not the ".outer" element,
because the outer element is not positioned at all. If we add a
position: relative to the .outer element, it does get clipped
correctly.

Shawn Singh

unread,
Jun 21, 2013, 2:34:10 PM6/21/13
to PhistucK, Alok Priyadarshi, sanjoy pal, Graphics-dev, sanjo...@samsung.com
oops - to be clear, I meant Sanjoy's second example is working as intended. =)

PhistucK

unread,
Jun 21, 2013, 4:54:49 PM6/21/13
to Shawn Singh, Alok Priyadarshi, sanjoy pal, Graphics-dev, sanjo...@samsung.com
Oh, damn...


PhistucK
Reply all
Reply to author
Forward
0 new messages