Andy Davies

Think Twice Before Using matchMedia to Conditionally Load Stylesheets

Christian Heilmann recent started exploring how matchMedia could be used to conditionally load resources based on viewport size and other mediaqueries - Conditional Loading of Resources With MediaQueries

I’ve experimented with using matchMedia to restrict the loading of social media buttons to larger viewports so I think using matchMedia to conditionally load content is a great idea but I was less convinced by the benefits of Christian’s example of conditionally loading CSS.

Ilya Grigorik had similar concerns when Scott Jehl created eCSSential, a loader that attempts to optimise the loading of CSS based on viewport size and other factors.

The question is what impact, if any, does conditionally loading CSS have on the performance of sites in real life?

For testing I used a static copy of Enoch’s Fish and Chip Shop as built by Matt Wilcox, hosted on an EC2 micro-instance in Dublin.

Enoch’s is typical of many of the sites showcased on mediaqueri.es as it uses separate CSS files for each breakpoint.

Other than changes to the CSS outlined below, the only other change made was enabling gzip using the configuration from HTML5 Boilerplate.

Three scenarios were tested:
1. Multiple stylesheets with browser determining load order
2. Multiple stylesheets with matchMedia used to load only those that apply
3. Single stylesheet containg all stylesheets merged into one

Each scenario was tested using the iPhone agent on WebPageTest with the median of 9 runs used for comparison.

Default iPhone Behaviour

Webkit based browsers prioritise the loading of CSS. Stylesheets whose mediaqueries match the current viewport as loaded first and any others deferred until later in the page.

The waterfall below demonstrates this split (highlighted in green) between the loading of CSS needed to render Enoch’s homepage and other CSS files.


Waterfall of network activity for Enoch’s Fish and Chip Shop on iPhone produced via webpagetest.org

Conditional Loading of Stylesheets with matchMedia

Unfortunately other browsers don’t behave in the same way as webkit and attempt to load all stylesheets before starting to render the page, so using matchMedia to conditionally load the stylesheets might offer a way to reduce the number of requests and so speed up page load times.

One drawback of using javascript to load CSS is the order resources are retrieved might be altered - the browser isn’t aware of the CSS resources until the script updates the HTML link elements and while the script is executing the lookahead preloader will schedule other resources for download, so the download of these resources may delay downloading the CSS.

This behaviour can be seen in the waterfall below, where other resources (highlighted in red) start to download before screen.320.css, and so delay its download.

Overall the loading pattern Christian proposes results in the page starting to render marginally later (1.80s vs 1.63s) but reaching document complete sooner (7.62s vs 10.94s).


Waterfall of network activity for Enoch’s Fish and Chip Shop on iPhone with stylesheets conditionally loaded using matchMedia.

There are other disadvantages to this approach too:

The sample code needs to be enhanced to allow for changes in viewport size or orientation so mediaqueries on the elements can be re-evaluated and appropriate resources loaded when necessary.

Browsers are continually trying to improve the way they load pages so it’s likely other browsers will adopt the same approach as Webkit and may not even load stylesheets that don’t apply or defer them until after DOMContentLoaded.

Finally not all browsers support matchMedia so some will need to use Paul Irish’s matchMedia polyfill.

Merged Stylesheets

Merging all the stylesheets together into a single downlaod is perhaps the simplest optimisation that could be applied. In this case it also results in the fastest start render (1.57s vs 1.63) and document complete (7.21s vs 7.62s) times.


Waterfall of network activity for Enoch’s Fish and Chip Shop on iPhone with stylesheets merged into one.

Comparison of Tests

Raw timings don’t always give a complete picture, so I always compare tests visually too.

Comparing the tests side-by-side demonstrates the test with the merged stylesheets is both first to start displaying ‘real’ content and also the first to complete.

The test using matchMedia completes before the original site most likely due to a lower number of requests but it is the last to start rendering ‘real’ content.

N.B. Watch out for the unequal timescale!

Filmstrip comparison of the three test scenarios.

WebPageTest also provides a comparison of visual progress and this re-inforces the matchMedia test is the slowest to start displaying ‘real’ content.


Illustration of progress towards visual completion for each test scenario.

Conclusion

In this case the simplest optimisation i.e. merging the stylesheets in one, produces the fastest result.

The combination of less requests and most likely the availability of all styles earlier in the pageload allows the page with the merged stylesheet to start rendering sooner, even though the combined stylesheet (14KB) is slightly larger than the two stylesheets downloaded by the matchMedia test (10.1KB).

Even the original page starts to render before the one that uses matchMedia, with DOMContentLoaded being delayed by the download of stylesheets that aren’t applicable. The WHATWG spec allows for the loading of stylesheets that aren’t applicable to be deferred until they are are needed so further optimisations may be possible.

Based on these tests and the likelihood of other browsers adopting behaviour similar to Webkit’s, I wouldn’t advocate approaches that use matchMedia to determine which stylesheets should be loaded.

Other Considerations

We should ‘poke holes’ in all tests and examine them for weaknesses, this test is no different and there are some areas for further exploration.

CSS is very repetitive (IDs, class names and CSS syntax itself) so it compresses well, dataURIs are the exception to this. The CSS on Enochs doesn’t contain any dataURIs so sites using dataURIs may see different results.

The iPhone test agent uses a UIWebView and execution of the javascript is impacted by the lack of a JIT. Delays in the download of screen.320.css were also seen when the matchMedia test was repeated in Safari on both an iPhone and the iOS simulator. The delays were not a great as those on the WebPageTest agent but they were long enough to allow other resources to start downloading.

The tests need repeating in other mobile browsers e.g. Firefox, Internet Explorer, Opera etc., and for other sites. I attempted to repeat the tests using Android 2.3 but even with a polyfill the test using matchMedia failed (a similar test using eCSSential works, so it’s not quite clear where the issue is at the moment).

Scott has seen performance improvements when eCSSential is used so we need more detail to be able to understand the cases where it makes a difference.

Raw Test Results

If you want to take a look at the raw results yourself, here’s the relevant tests on WebPageTest:

Default iPhone Behaviour
webpagetest.org/result/121228_66_a9708983b3a994bc3345e4f66858c59c/

Conditional Loading of Stylesheets with matchMedia
webpagetest.org/result/121228_BA_52d204278ed082e081c4cdffac110358/

Merged Stylesheets
webpagetest.org/result/121228_JZ_c100646a583ed1d3789db3d4e37629c5/

Comments