CSS and performance?
If you take the average application and compare the weight of your CSS files with the weight of the JS ones, specially when dealing with JS frameworks, worrying about the performance of the CSS in terms of weight or requests, may not seem so crucial. But it actually is. There are multiple evidences of the strong impact even minor improvements in performance can bring.
For every 100ms decrease in homepage load speed [there was] an average annual revenue increase of $376,789
100ms worth more than $376,000? Does CSS performance matter now? Let’s approach it based on our CSS decissions and be aware of the consquences they have. To do so, we will check our implementations from the previous articles.
We linked in our markup to the Bootstrap CDN which serves all the CSS whith the classes needed.
The head of our HTML looked like this:
&lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt; &lt;meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" /&gt; &lt;link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"&gt; &lt;link href="./styles/min/style.css" rel="stylesheet" &gt; &lt;title&gt;Bootstrap CDN hosted&lt;/title&gt; &lt;/head&gt;
First thing we notice here is that we are requesting two CSS files. The first file is the Boostrap CSS, while the second one is the one used to style our page. Nope, this is not good.
When we decided to link to the Bootstrap CDN sure it seemed to be a good option- we get all the framework with just one link, saving us a lot of time. Actually, it saves time if we don’t mind others wasting theirs.
To download each of those CSS files an HTTP request happens. For each HTTP connection to be established, the browser has to resolve the domain name for each domain we are trying to connect to, establish the connection with it, send the request, wait for the response and then load it. Furthermore, there is a limit in the number of simultaneous requests that a browser can establish and we are using one of them.
In our example we send two requests: one to our server, one to the Bootstrap CDN. For each of them, the whole process described above has to be repeated as they are requests to different domains. So, we are unnecessary consuming some milliseconds here.
We already know that regarding the number of requests and the time they consume, we are not starting very well. Those are consuming our performance budget and we have just started! Let’s start the developer’s tool console and check what happens when requesting our site.
As for the whole article, each test is performed under the same conditions: Files locally served from a local Apache server. Gzipping is enabled and to simulate a real-world scenario, throttling is enabled as a regular 3G connection.
We are just seing the CSS requests in this screenshot. Total transfer: 23.6 KB, of which 23 KB are for minified and gzipped Bootstrap.
How much time did you say Bootstrap was saving you? In this case it is taking away 136.75 ms from the relation between our site and the user since our own stylesheet was already downloaded. If we go back to the study mentioned above and make a fast estimation, this delay would cost our client as much as -more than- $500,000/year.
The optimal number of requests in no request
Anonymous, XXI c.
Actually this is well illustrated in this example. We are downloading the exact same lines of code but with just one request and we are saving some time.
The main difference with the previous option is that we are integrating Bootstrap CSS code with ours. This is not a big change as we are producing the same number of lines code, but we are in the good way as we are saving one HTTP request and some milliseconds with it. More precisely, we are saving 38,11ms. That is a 20% save in just one move!
Same as before, we are still saving that one extra request from the beginning and now there is even a huge weight loss as we are just importing that part of Bootstrap we are interested in: the grid.
The importing diet worked. Our site now downloads below 54ms. That was a really time saving move. We are already under 1/3 of the time we started with. This should give us and idea of how we were forcing the user visiting our site to swallow way too much meaningless code for our site. For that matter, we are also saving some compilation time. Please, don’t be lazy, if your option is Bootstrap, customize your CSS based on your real needs.
And, just to feed our curiosity, let’s see the difference in performance with Bootstrap grid self hosted but not integrated with our CSS.
Wait, wait, wait. 3.4KB when served as an independent file? What’s going on here? Why Bootstrap grid system CSS is heavier when not imported together with our styles? I actually doublechecked it. I thought that maybe Apache was not gzipping. It was, so I checked what’s inside the file. Bootstrap happens to pack into your custom download a CSS reset. This makes the file heavier than our custom Bootstrap grid import. So, almost 15ms slower thant our option but still lighter than the whole Bootstrap, though.
Bootstrap grid mixins
Using Bootstrap mixins to create our own classes is the second step to become cool developers. Not just for the fact that we are going to decide what our class names are going to look like. And this is because here we are going to be as honest using Bootstrap as it is possible. The only code delivered to a user will be the exact lines we will need.
Until now we were using Bootstrap adding classes to our html. We just used them where we needed to implement a given behavior for our layout. This was possible because all 12 column width variations for four different viewport sizes plus utility classes have been previously been compiled and are available to be used in our stylesheet.
So we go back to that moment before compiling and we wish we could go back and change something and we do it! We customize our import and we don´t generate the complete Bootstrap grid system but use the code to create the behavior we are looking for. And we do it by using the most basic elements used, the mixins.
Sass mixins work by generating a given code in the place they are called from. Oh, and they can accept parameters to adapt that code, of course. So, we are going to call that mixin to create a 2 column width element in middle-sized viewports in each element we want to be displayed with that width, for example.
Anyone could argue here ´hey, are you telling us to stop importing Bootstrap bloat to generate our own bloat?’ Yes, actually it’s what we are doing 🙂
What sense does it make? A lot, indeed. We already agreed that we have super cool semantic classes and not class names based on behavior or appearance. Besides, what we are doing now is generating code that may eventually be repeated as many times as a given mixin is called and here comes into play gzip.
The way Gzip works is very well explained in this informative article by Julia Evans: what Gzip basically does is looking for repeated patterns and replace those repetitions with pointers. Therefore, gzip goes along so well with Bootstrap mixins. When called, the mixins will generate a code pattern which may be repeated more than once without hardly penalizing in weight the final download.
Big jump in performance here. This is due to the weight cut on Bootstrap after leaving out everything and just generating the code we need for the layout we need.
CSS Grid Layout
We reached the last tool used to implement our basic grid layout: CSS. Just pure CSS. No framework, hacks or whatsoever. No extra http requests or wrappers. Just some CSS rules for which the user browser is (will be) ready.
How many extra lines of code did we write here? Well, a couple of them, but not that much actually. We could have done it otherwise, without a grid, because it is a rather basic layout. But, think about a more complex example for which we would definitely need a grid system. With CSS Grid Layout this system is for the first time in the history of CSS ready to be used in the browser. There is no need to serve it to the client.
Did you see that? Go and check where we started. I’ll tell you: 184,75ms! So, yes, we saved a 75% time in our CSS request-download time. High five to us!
Sure CSS Grid Layout module is not production ready yet. But see how fast does it move forward. At the time of writing this article this module transition from being a draft – this is the the W3C terminology for a working in progress – and it moved into Candidate Recommendation (September 29th, 2016).
During this Candidate Recommendation phase the module is widely tested in the different browser to shape it into its final form (some features may drop from the specification) and then it will move then into Proposed Recommendation level before being part of the W3C standard, named W3C Recommendation.
Some CSS Grid Layout module experts foresee it being widely available as soon as early 2017. Let’s help make it happen! And in the meanwhile consider making all you can to improve your CSS performance.
What we learnt in this article
- CSS performance matters
- The fastest developing option is not always the best solution for the user.
- Frameworks can and should be used customized to our needs, never as they are.
- CSS Grid Layout Module is a big time saving tool both for developing and for the final user.