Modernizr might be making your site slow, especially on mobiles
Recently, a colleague was analysing a client’s site and noticed that performance on mobile was about one second slower than expected, with a gap in the WebPageTest waterfall with no network traffic. We did some digging on desktop and could not replicate the one second of missing network time, although there was a clue hidden in the high CPU usage on the browser main thread, visible in the WebPageTest waterfall:
Something on the page was consuming the browser thread and blocking critical content including web fonts - meaning no text was rendered until this process had completed. I decided to find more sites using Modernizr to see if the issue could be replicated - it could.
Note that the bulk of the time spent on this script is in one function - s.csstransforms3d. Following the stack you can see that this function causes a style recalculation. A quick bit of digging into the Modernizr source identifies the cause. The script injects an element and then uses functions offsetLeft and offsetHeight to test whether a CSS 3D transform has worked on the injected element:
This process makes sense - these offest function calls are a predictable way to test for the size of a DOM element on screen. In order to calculate the size of the injected element these functions trigger a reflow, in order for the browser to tell you the true size of an element it must ensure that all DOM manipulations (such as 3D transforms) have been executed. Causing a reflow is generally considered bad for web performance, Stoyan Stefanov wrote a great post on this way back in 2009.
Now, in order for Modernizr to do its thing properly it must load early. Here’s what the Modernizr documentation says:
The reason we recommend placing Modernizr in the head is two-fold: the HTML5 Shiv (that enables HTML5 elements in IE) must execute before the <body>, and if you’re using any of the CSS classes that Modernizr adds, you’ll want to prevent a FOUC.
So, what do we do about it? First off, check if your Modernizr build runs the CSS 3D transforms check. If it does, make sure it is necessary and if not, remove it from your build using the Modernizr production download tool.