title: Why does Chrome not need to repaint the entire layer on a change?
body: <p>I am trying to understand, in practice, how the layout &rarr; paint &rarr; composite pipeline of Chrome works. During my testing, I got confused about Chrome's behavior in the following situation. <a href="https://codepen.io/mkarajohn/pen/gvJgXx" rel="noreferrer">(Codepen)</a></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var button = document.querySelector('button');
  var red = document.querySelector('.red');
  var blue = document.querySelector('.blue');
  button.addEventListener('click', function() {
    red.classList.toggle('test');
  })</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>.wrapper {
    height: 100%;
    width: 100%;
    background-color: teal;
    position: static;
  }
  
  .square {
    height: 200px;
    width: 200px;
    position: static;
    transition: transform 0.3s ease,
      opacity 0.3s ease,
      width 0.3s ease,
      height 0.3s ease,
      box-shadow 0.3s ease;
  }
  
  .red {
    /* position: absolute; */
    background-color: red;
    top: 100px;
    left: 100px;
    /* will-change: transform; */
    opacity: 1;
  }
  
  .blue {
    background-color: blue;
    z-index: 3;
  }
  
  .test {
    /* transform: translate3d(50px, 50px, 0); */
    /* opacity: 0; */
    width: 60px;
    height: 60px;
    /* box-shadow: 0px 0px 0px 10px rgba(0,0,0,.5) */
  }
  
  button {
    position: fixed;
    right: 100px;
    top: 50px;
    z-index: 10000;
    font-weight: bold;
    background-color: yellow;
    padding: 5px 10px;
    /* will-change: transform; */
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div class="wrapper"&gt;
    &lt;div class="red square"&gt;&lt;/div&gt;
    &lt;div class="blue square"&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;button&gt;Click&lt;/button&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>To reproduce.</strong></p>
  
  <ul>
  <li>Use Chrome;</li>
  <li>turn <em>Highlight repaints</em> on, in the dev tools;</li>
  <li>open the <em>Layers</em> panel;</li>
  <li>click the yellow button to toggle the size of the red square;</li>
  <li>see what is highlighted as "repainted", as well as the current layers;</li>
  <li>try doing it after changing the <code>position</code> of the red square too.</li>
  </ul>
  
  <p>We have two squares, a red one and a blue one, inside a wrapper element. In Chrome's <em>Layers</em> panel this whole thing shows as one layer.</p>
  
  <ul>
  <li><p>If both squares are <code>static</code> positioned, when I transition the width and height of the red one, I can see that the whole layer gets repainted, which, to me, makes sense, since, if all 3 elements are in the same layer, changing the dimensions of one, changes the whole layer's end result, so the whole layer has to be repainted.</p></li>
  <li><p>If I set the red square to <code>absolute</code> positioning (you can do that by uncommenting the line in the <code>.red</code> style rules), when I transition its width and height, even though the dev tools still show one layer, only the red square, inside that layer, is shown as repainted. </p></li>
  </ul>
  
  <p><strong>Question.</strong><br>
  The second scenario does not make sense to me.</p>
  
  <p>If the two squares and the wrapper element are all in the same layer, shouldn't changing one element affect the whole layer and cause the layer as a whole to repaint, instead of just the red square?</p>
  
  <p><strong>Additional questions.</strong><br>
  Does Chrome, during the layout phase (or whatever phase it is that determines the layers) separate some elements into their own layers (due to <code>position</code> properties for example)? Is that why it is able to repaint them separately? Does it, after the compositing phase, dump them, so the developer only sees one layer in the dev tools?</p>
  
  <p><strong>Related background.</strong><br>
  My rough understanding of the painting process of modern browsers is as follows:</p>
  
  <ul>
  <li>During the layout phase, the browser combines CSS with HTML information in order to figure out positions and dimensions of visual elements on screen. I also believe this is the time where it determines how many render layers are there (due to <code>will-change</code> for example).</li>
  <li>During the paint phase, the browser makes a framebuffer for each layer, containing information about what color each pixel should display, based on the layout data.</li>
  <li>During the compositing phase, the GPU composites all the layers together, based on the data generated during the paint phase, and sends the final result to the screen.</li>
  </ul>