14

Take a look at this CodePen to see what I mean:

.perspective-container {
  margin: 50px 0;
  perspective: 1000px;
  perspective-origin: 0 50%;
}
.card {
  border: 10px solid blue;
  width: 300px;
  height: 300px;
  overflow: hidden;
  transform: rotateY(-45deg);
}
.card-inner {
  width: 300px;
  height: 300px;
  overflow: hidden;
}
.scroller {
  transform: translate(0, -100px);
}
.scroller-3d {
  transform: translate3d(0, -100px, 0);
}
.will-change {
  will-change: transform;
}
<h1>Incorrect (uses will-change):</h1>
<div class="perspective-container">
  <div class="card"><div class="card-inner">
    <div class="scroll-container">
      <div class="scroller will-change">
        <img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
      </div>
    </div>
  </div></div>
</div>
<h1>Incorrect (uses translate3d):</h1>
<div class="perspective-container">
  <div class="card">
    <div class="scroll-container">
      <div class="scroller-3d">
        <img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
      </div>
    </div>
  </div>
</div>
<h1>Correct (uses neither translate3d or will-change):</h1>
<div class="perspective-container">
  <div class="card">
    <div class="scroll-container">
      <div class="scroller">
        <img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
      </div>
    </div>
  </div>
</div>

I have a rotated element with perspective applied, inside of which I have a 'scrolling' div which is transformed vertically (imagine a magazine page-turn experience with scrolling divs inside each page). I added will-change: transform to the inner div and that broke the outer container overflow: hidden. This seems to be a bug with the Chrome compositor.

Does anyone know of any workarounds? I would like to keep the will-change attribute because it significantly speeds-up animations on mobile Chrome.

Edit: It looks like this is not specific to the will-change property but any property that makes the inner div its own compositing layer. When I remove the will-change property but change the transform to a translate3d that similarly improves performance and exhibits the bug. The only class on the inner div that allows the rotated parent to correctly render overflow: hidden is the one that adds the 2D transform.

sergdenisov
  • 8,327
  • 9
  • 48
  • 63
Duane Barlow
  • 183
  • 8
  • 1
    To make things more complicated, I tried `transform: translateZ(0);` instead of `translate3d` and it masks the top but not the bottom of the graphic! – Jason Lydon Apr 29 '15 at 00:51

1 Answers1

3

Try something like this CodePen:

.container {
  margin: 75px 0;
}

.card {
  border: 10px solid blue;
  width: 300px;
  height: 300px;
  overflow: hidden;
  -webkit-transform: perspective(1000px) rotateY(-45deg);
  transform: perspective(1000px) rotateY(-45deg);
  -webkit-transform-origin: 0 50%;
  transform-origin: 0 50%;
}

.scroller {
  -webkit-transform: translate(0, -100px);
  transform: translate(0, -100px);
}

.scroller-3d {
  -webkit-transform: translate3d(0, -100px, 0);
  transform: translate3d(0, -100px, 0);
}

.will-change {
  will-change: transform;
}
<h1>Uses will-change:</h1>
<div class="container">
  <div class="card">
    <div class="scroll-container">
      <div class="scroller will-change">
        <img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
      </div>
    </div>
  </div>
</div>

<h1>Uses translate3d:</h1>
<div class="container">
  <div class="card">
    <div class="scroll-container">
      <div class="scroller-3d">
        <img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
      </div>
    </div>
  </div>
</div>

<h1>Uses neither translate3d or will-change:</h1>
<div class="container">
  <div class="card">
    <div class="scroll-container">
      <div class="scroller">
        <img src="https://images2.pixlis.com/background-image-horizontal-lines-and-stripes-seamless-tileable-grey-black-22hnju.png" />
      </div>
    </div>
  </div>
</div>

You could play with perspective() and transform-origin values.

sergdenisov
  • 8,327
  • 9
  • 48
  • 63
  • 2
    Thank you Sergey! So the fix is to use perspective inside the transform on the card element rather than the perspective attribute on the container. I'm interested in why this fixes it, I'll look into the difference between the two approaches but this solves my problem perfectly. Thanks again! – Duane Barlow May 04 '15 at 03:38