- No frame should exceed 16ms
- Caveat: really only the duration between when an animation starts and ends do we need 60fps
- Do expensive operations before and after an animation
- Never trigger a forced sync layout (layout thrashing)
- In the above image, the highlighted methods are deferred to the end of the frame due to browser optimization steps. As a result, the second method now overrides the first method and the resulting effect is that the first method never happened. Net effect: no animation.
- In this case, we need to force the browser to recognize that we've set some styles before we start changing them again.
- In order to resolve this, we need to access a property of the element that forces a layout (such as width or height) in order for the browser to register the change.
- Caveats: this technique should be done before animations begin and should be performed only once!
- Never Sniff the User Agent String
- Do UA sniffing only as a way to provide the best experience to your users on every platform
"Users really feel it, they may not be able to say what it is but it matters to them. ~ Paul Lewis
In order to render elements to screen the browser makes use of two threads called the main thread and the compositor thread.
The main thread is tasked primary with:
- Running your JavaScript.
- Calculating your HTML elements’ CSS styles.
- Laying out your page.
- Painting your elements into one or more bitmaps.
- Handing these bitmaps over to the compositor thread.
The compositor thread is used primary for:
- Drawing bitmaps to the screen via the GPU.
- Asking the main thread to update bitmaps for visible or soon-to-be-visible parts of the page.
- Figuring out which parts of the page are visible.
- Figuring out which parts are soon-to-be-visible when you’re scrolling.
- Moving parts of the page when you scroll.
When we animate properties such as height, we get the following communication pattern between the two threads. Note: Expensive operations are in orange.
When we use transforms or transitions, properties easily mainupalted by the GPU, we get the following pattern:
When animating height and width on an element, you will still get visual "jitter" due to the fact that the element is being animated pixel by pixel. Constrastly, you get subpixel rendering when you use a transform.
// Through the use of getBoundingClientRect on an element, we get an object that looks similar to this:
{
top: 178,
left: 201,
width: 234,
height: 240,
bottom: 418,
right: 435
}