Is CSS-in-JS really bad for UX?
I’ve been reading a lot of misconceptions regarding CSS-in-JS performance implications and how it can be harmful for user experience. In a nutshell, the message they all are delivering is that JS developers are too focused on DX (Developer eXperience) and keep forgetting about how important performance for UX (User eXperince) is.
UX is not just about speed
One of the misconceptions I keep seeing is that people think speed is the most important part of user experience. UX is much more complex as just delivering CSS to the client.
Usability, accessibility, consistency, affordance, security, and the language you’re using in your application are equally important aspects contributing to the UX along with how fast things are happening on screen. Customer support and how delightful your interface is are also parts of UX. So, probably, focusing just on one aspect and measuring it in isolation won’t tell you a lot about how good the UX is?
The thing is: to build consistent, accessible and fast UI is freaking hard job. And UI developers are trying to find a way to simplify it as much as possible. By doing so we can reduce the time to deliver new features that are less buggy, work faster and in a more consistent way. So, as you can see, by investing into #DX you’ll get a better #UX in the result.
Do not trust microbenchmarks
I’ve been stupid enough to write code like this:
var num1 = ~~str; // convert strings to integers like an asshole
instead of writing it like this:
var num2 = parseInt(str, 10); // explicit conversion
because someone made a JSPerf comparing those 2 and the ~~
was hundreds of times faster. Well, you know what? That benchmark was measuring nothing. Vyacheslav Egorov does a great job explaining why you should not trust microbenchmarks in in his talk:
Next time you see a tweet like this:
please ask yourself (or better the author) what are we actually measuring and how relevant it is to your application.
I guess not many web applications will update styles on DOM nodes hundreds of times a second like this benchmark is doing. And remember, browsers are smart at optimizing things based on heuristics. It wouldn’t surprise me if this benchmark is measuring nothing for the classNames/classlist examples because it is smart to eliminate unnecessary reflows. We don’t know that because browsers are black boxes and it’s hard to measure and optimize something we don’t completely understand.
Speed is a very perceptive thing
Just by measuring speed in DevTools it’s might be hard to say how people will perceive it in reality. Sometimes you even have to slow things down to get a better UX ¯_(ツ)_/¯, so it’s more a design problem. “The Way You’re Measuring Your Web Performance Is Wrong” does a good job explaining why it is wrong to measure only technical aspects of things.
Don’t get me wrong: I’m not saying that load and startup performance is not important (see below). All that I’m saying is that we should look broader when talking about UX.
Readability > Speed
As I said before when people talk about the speed they often take it out of context. Articles comparing React to vanilla JS code proving that React is slower than a vanilla code. Similarly, there are people proving that CSS-in-JS is slower than vanilla CSS.
Here is the thing: building complex systems (as opposite to just simple demos or showcases) is really hard and it is even harder to do by using low-level abstractions (read, “vanilla”). Depending on how complex the system you’re building, you’ll probably end up with lots of unmaintainable spaghetti code that even people who wrote it wouldn’t understand a couple of months later.
That’s why declarative APIs like JSX (HTML-in-JS) are better abstractions than just HTML markup plus a “sprinkle” of jQuery on top of it.
If you still don’t understand why JSX (HTML-in-JS) is a good idea, you should watch this talk by Cheng Lou called “On the Spectrum of Abstraction”:
When you begin to treat your UI as a design system (i.e. independent components that can be composed in a variety of ways) and not as documents and links, you’ll realize pretty quickly that CSS offers a wrong level of abstraction here.
That’s why we have been using BEM, SMACSS and other methodologies — we introduced a new level of abstraction on top of CSS that prevented us from screwing things up every time someone touched CSS. We created an abstraction that has some contracts (i.e. how we name things) to gain predictability and better readability (i.e. less cognitive load to understand a piece of written code). CSS-in-JS takes this even further by putting it closer to the source code of your components.
Of course, this also comes with a cost: now we have to use build tools that would extract it back to “vanilla” CSS (because it’s good for performance, sigh!) or pay some performance penalties if executed in runtime.
So, no, it’s not just about saving an “Alt-Tab” keypress. It’s about building a system with specific contracts and guarantees.
Same way React’s strengths aren’t about VDOM vs DOM performance (another common misconception), CSS-in-JS is not about how fast you can write it and deliver it to the client.
Performance matters
Loading performance matters, of course, and we as developers are obligated to do our best job to ensure the web is still accessible and open for everyone. Good news are: developers are aware of those problems and are striving to improve:
As with any evolutional or explorational process, it might be not the main focus in the beginning. Projects like 💅 styled-components offer great ergonomics at some runtime costs. Now we see projects like JSS picking it up and providing you with the same but more performant API. Solutions that allow writing styles in a most ergonomic and safe way and extract them at build time will help us to get best of both worlds.
Projects like webpack that allow split and lazy-load your code easily, combined with features like PWA Performance Budgets and projects like Prepack will make our applications even faster.
Conclusion
Ultimately, we should focus on building great products with the best possible user experience. This usually involves different people with different backgrounds working on the same thing so any technology that could improve inter-communication between them is helping them to deliver better UX of the product.
Projects like react-sketchapp and 💅 styled-components are helping CSS and JS developers and designers to work with same abstractions and share the knowledge across the team enabling faster feature releases, shorter feedback loops and, in the end, better UX! 🙌