Fast is better than slow.
Google's Ten Things, #3

The Need For Speed

Web applications are rife with opportunities to optimize performance.

  • Redirects
  • Authentication
  • Data lookup
  • Network delay (initial payload)
  • JS execution
  • Rendering

Optimization efforts often focus early in the request. Those extra milliseconds of paint time at the end feel like a drop in the bucket.

The Need For Speed

In the Browser

It turns out that the time closest to the user is incredibly important — it can make or break the "snappiness" of your app. Proof!

Freeing up the UI thread with blisteringly-fast JS is key.

…but it's not enough!

Fast Rendering

Cutting down render time has traditionally been an exercise in tedium.

Tools of the trade

  • Chrome DevTools
  • Profilers
  • Timeline

CSS Performance

Know Thine Enemy

  1. Style recalculation
  2. Paint

The Rendering Cycle

Reverse-Engineering the Timeline

The Rendering Cycle

Edits to the document cause the browser to enter the rendering cycle.

  1. Build the DOM
  2. Calculate CSS property values
  3. Build the rendering tree
  4. Calculate layout
  5. Paint
  6. Composite

Understanding each step can help diagnose slow rendering.

Build the DOM

The Rendering Cycle

The Document Object Model (DOM) is an API for HTML documents. It provides a tree representation of the document, which JavaScript can interact with.

An accurate DOM tree is a prerequisite for all other rendering tasks.

This tree is reflected by the DevTools Element Inspector.

        var el = document.getElementById('confirm');
        el.innerText = 'Success!';
        el.appendChild(successIcon.cloneNode());
      

Calculate CSS property values

The Rendering Cycle

The browser must calculate the value of every CSS property, for every element on the page.

        <button id="menu-button">
          Toggle
        </button>
      
        #menu.closed {
          color: rgba(0, 0, 0, .9);
        }
        #menu:hover {
          box-shadow: 0, 0, 3px, rgba(0, 0, 0, .3);
        }
        #menu[disabled]:hover {
          box-shadow: none;
        }
      
        var menuBtn = document.getElementById('menu-button');
        menuBtn.classList.add('closed');
        menuBtn.setAttribute('disabled', true);
      

Build the Rendering Tree

The Rendering Cycle

This is a data structure that helps the browser perform layout tasks. Its contents and shape may differ significantly from the DOM.

DOM treeRendering tree
ContentElements and nodesBoxes
Parenting strategyHTML parentContaining block

Build the Rendering Tree: Elements vs. Boxes

The Rendering Cycle

  • <div style="display: none">
  • <head>
  • <script>
  • <style>
  • line box
  • ::before
  • anonymous box
  • <div>
  • <span>
  • <a>

Build the Rendering Tree: Containing Blocks

The Rendering Cycle

A box's containing block determines where and how it is rendered. Its rendering type determines its containing block.

Most boxes are contained by their DOM tree parent. This includes boxes in normal flow (e.g. block, inline) and floats.

Absolute boxes are contained by their closest positioned DOM ancestor.

Sometimes anonymous boxes are inserted, but this doesn't affect performance.

Build the Rendering Tree: DOM Comparison

The Rendering Cycle

        <sectionsectionsection style="position: relative">
          <divdivdiv>
            Meh literally#Meh literallyMeh literally <navnavnav style="position: absolute">vice#vicevice</nav> american apparel.#american apparel.american apparel.
          </div>
          Fixie freegan sriracha,#Fixie freegan sriracha,Fixie freegan sriracha, <spanspanspan>direct trade#direct tradedirect trade</span> food truck.#food truck.food truck.
        </section>
      
Rendering tree
          block box: 
            block box: div Meh literally american apparel.
            absolute box: nav vice
            anonymous block box
              anonymous inline box: Fixie freegan sriracha,
              inline box: span direct trade
              anonymous inline box: food truck.
        
DOM tree

Build the Rendering Tree: Relevant Properties

The Rendering Cycle

  • display
  • float
  • position

The rendering tree also affects layering; more on that shortly.

Layout

The Rendering Cycle

Calculate the position and dimensions of every box.

Relevant properties:

  • height
  • width
  • padding
  • border-width
  • margin
  • coordinates (top, right, bottom, left)

Paint

The Rendering Cycle

Determine what color to paint each pixel, create a bitmap, and upload to the GPU.

Transparency can be expensive, especially anti-aliased text.

Chrome paints layers individually. Particular HTML and CSS will invoke a layer, but note this is a Blink/Chrome implementation detail rather than specified behavior.

Composite

The Rendering Cycle

Layer bitmaps are transferred to the GPU, combined ("composited"), and drawn on the screen.

Relevant properties:

  • opacity
  • transform

The Rendering Cycle

  1. Build the DOM
  2. Calculate CSS property values } style recalculation
  3. Build the rendering tree } layout
  4. Calculate layout
  5. Paint painting
  6. Composite compositing layers

Demo Time

Rendering Hit List

  1. Eliminate JavaScript interruptions
  2. Eliminate layout
  3. Minimize paint rectangles
  4. Eliminate painting altogether

Appendix

Further reading

Thank you!

chelsea-derrick.appspot.com/io2013