How to increase CSS-in-JS performance by 175x

I like the convenience of CSS-in-JS especially being able to co-locate styling but I’m not convinced on a few of things:

  1. That hashed classes are a “must have” since name clashes are easily avoided in apps with good (and readable) naming, and arguably annoying on 3rd party components when you just really needed to select an element with a nice semantic class but can’t.
  2. That turning your CSS into a tangled mess of props and logic is all that good of an idea, which can make it less readable but also leads to terrible, and I mean terrible loss of performance.
  3. That it’s a good idea to add 28kb to 40kb of minified JavaScript to your 10kb NPM component.
  4. That you have to fiddle with build tools (restricted in Create React App for example) to try and optimize the CSS. Which by the way doesn’t do anything clever like optimize parsing times; it just minifies, removes comments, adds source maps etc.

At first you go on your merry way and don’t notice any performance problems with these “blazing fast” runtime CSS solutions. That is until you put a bunch of them on one page in Storybook.

Let’s look at the ubiquitous Button component as it has various styles and options:

Image for post

We then had a bunch of simple and fast functions to compose the styles. We even optimized the static css to be it’s own chunk (sharedStaticButtonStyles):

Image for post

Our Button component had the most dynamic function calls and the most elements in Storybook. Let’s see how it performs to load.

Image for post

That’s around 36 seconds spent on Emotion parsing (see red underlines). The Performance tool makes it about 2–3x as long, which is still far too long.

It gets worse

I initially blamed a Tooltip component for being slow to show itself, then realized it was only when attached to a Button. It was then that I realised Emotion is parsing the CSS again on hover I guess because the Tooltip causes a re-render, and freezing the main thread for about 900ms before the tooltip could show:

Image for post

You might be thinking “well my components aren’t that complicated or slow”. Even if they are twice as fast for me on a large app with many components on a page, spending 1–2 unnecessary seconds frozen on load while CSS is parsing is unacceptable. Especially on the kind of apps that I build which are highly dynamic and receiving many updates per second (which Emotion is re-parsing every render like it does on hover due to the dynamic nature of the props based styling).

So how can we make and keep things fast?

Firstly if you’re starting a new project you may want to consider compile-time CSS-in-JS solutions:

But if not no worries, you can increase performance of your existing styling by up to 175 times by making your CSS more static.

There are already various write ups on how using props theming litters your application with 100s of HOC wrappers —

And if I was starting a new project I would use CSS Variables for theming instead, I’ve already written on how to do that:

But that’s not your performance bottleneck

Your performance bottleneck is in those nested function calls in your css which accept props other than the theme.

Image for post

I haven’t delved into the depths of runtime CSS code but it seems that if you call a function then it basically says “I don’t know what this is going to return so I’ll recalculate it every render”.

Data attributes and CSS Variables to the rescue

Let’s change the way we do that Button component:

Image for post

The interesting thing here is the use of CSS Variables, this also allows us to drastically reduce the amount of static CSS we need to write.

Here is a refactor where I kept the old functions to derive colours and sizes, but moved them from Emotion CSS to CSS Variables in an almost 1:1 refactor:

Image for post

This function executes first time in about 0.002 milliseconds. Anyway let’s take a look at what the Button CSS now looks like:

Image for post

Remember it took 36 seconds of parsing time? Let’s see now:

Image for post

Yep, now it’s taking just over 200 milliseconds to parse the CSS. Remember with Performance recording off these numbers will be 2–3x smaller.

So in summary:

  • Consider compile time CSS in new projects (linked above)
  • Use CSS Variables for theming in new projects
  • Keep your CSS as static as possible for variations (the most important optimization)

Author: Shantun Parmar

6 thoughts on “How to increase CSS-in-JS performance by 175x

  1. I needed to post you that little bit of observation to say thanks once again for your personal magnificent principles you’ve featured in this article. It is quite remarkably generous of people like you to give openly just what a number of us might have marketed as an e book to generate some dough for themselves, most notably given that you could possibly have done it if you ever decided. These points as well served to be a fantastic way to fully grasp other people have similar fervor much like my own to know the truth lots more pertaining to this issue. I am certain there are millions of more fun opportunities in the future for individuals who looked at your blog post.

  2. I wanted to put you the tiny remark to be able to thank you over again on your precious suggestions you have provided on this page. It was really strangely open-handed with you to make unhampered precisely what many people would’ve offered for sale for an ebook to get some money for themselves, particularly now that you might have tried it in case you desired. These solutions in addition served to be the good way to know that some people have the identical interest really like my personal own to learn more and more when considering this matter. I believe there are several more pleasant sessions in the future for many who read through your site.

  3. My wife and i were very satisfied when Peter managed to finish up his survey while using the precious recommendations he received when using the weblog. It is now and again perplexing to simply possibly be offering tips which usually some people might have been trying to sell. We see we now have you to thank for this. These illustrations you made, the straightforward website navigation, the relationships your site make it possible to promote – it is mostly terrific, and it is making our son in addition to us recognize that this theme is satisfying, which is certainly unbelievably serious. Thanks for the whole thing!

  4. My wife and i were so relieved when Michael managed to finish up his studies via the precious recommendations he obtained using your web site. It is now and again perplexing to simply happen to be offering things which often some people might have been trying to sell. We remember we now have you to thank for this. The type of illustrations you made, the straightforward website navigation, the relationships your site make it easier to promote – it is mostly superb, and it is letting our son in addition to us recognize that this subject matter is pleasurable, which is certainly truly serious. Thanks for the whole thing!

  5. I’m also commenting to let you be aware of of the brilliant discovery my child encountered checking the blog. She came to understand a lot of details, including how it is like to have a marvelous coaching character to get certain people completely comprehend a variety of complex issues. You actually did more than her desires. I appreciate you for coming up with such essential, dependable, edifying and cool guidance on that topic to Ethel.

Thanks for your support, You may click on ads to encourage us which assits to writers.

Leave a Reply

Your email address will not be published.