DEV Community

Cover image for Don't Trust the Cascade - Why I write CSS in JavaScript
Paul McBride
Paul McBride

Posted on • Originally published at paulmcbride.net

Don't Trust the Cascade - Why I write CSS in JavaScript

If you've been on the internet recently, you've probably heard of CSS-in-JS.

The technology has been growing in popularity recently but not everyone is a fan. Today, I'd like to demystify what it is and why I think you should be using it.

A tweet that explains the C in CSS stands for JavaScript

CSS-in-JS can mean a few things, but primarily it is used to describe the technique of authoring styling logic in JavaScript. This can be done in the form of inline styles attached to a react component or by leveraging a tool like Styled Components.

Now, if you're anything like me, when you first heard the term CSS-in-JS you probably thought:

Oh no... not another thing I have to learn!

I have good news though if you already know CSS, you don't really have to learn anything new. But wait, if you already know CSS, then why bother writing CSS-in-JS, doesn't that just add complexity?

Why I Write CSS-in-JS 🎨

CSS stands for Cascading Style Sheets. Back when CSS was created, we were building websites which were typically pretty simple by today's standards. At the time, the cascading part of CSS was super useful. Today, however, I think it ends up being a foot-gun more often that it is helpful. Think about it, can you remember every class name you used on your last project?

Now imagine working on a project with several other people. Writing CSS that conflicts with or overwrites someone else's styles is essentially inevitable. Techniques like BEM and SMCSS can help but you have to rely on all developers following the rules and as a project grows so do the chances that someone will slip up.

For me, CSS-in-JS and Styled Components in particular help save me from myself. I'm protected from my own mistakes by an API instead of by convention. CSS-in-JS allows me to focus on styling my UI without having to be mindful of overwriting CSS somewhere else.

The cascade can still be useful, however. With Styled Components, you can still take advantage of the cascade but it is limited to the scope of the component you're working on. You can have your cake and eat it.

Performance 🚀

Okay, let's say you never make mistakes. Are there any benefits to CSS-in-JS besides controlling the cascade. As it turns out, there are. CSS-in-JS libraries are responsible for how styles are injected into the DOM. They can track which components are rendered and only inject the styles required.

This means the user ends up downloading fewer bytes of code and will have a quicker time to first paint. Great success.

Maintenance 🔧

Have you ever wanted to remove some CSS from a project but you had no way to be sure it wasn't being used somewhere. With CSS-in-JS, this usually isn't a problem as styles are typically co-located with the component that relies on them. You'll never have to go hunting for the CSS that is affecting the component your working on again.

Dynamic Styles

Another benefit of using CSS-in-JS is that you can take advantage of the power of JavaScript. You can use functions to create mixins and reusable style modules, props can be used to create variations of components and variables can be used for theming.

Most CSS-in-JS tools give you all the benefits of traditional CSS preprocessors too, including nested rules and auto-vendor prefixing.

What are the disadvantages of CSS-in-JS

All tech choices involve some sort of compromise and using CSS-in-JS is no different. The primary drawback of using something like Styled Components is the added complexity. First of all, it needs to be installed from npm. Not a big deal, but it is one extra step.

If you are sever rendering your code, you're going to need to install and configure a babel plugin to make sure your styles work on the first load too.

The other drawback of CSS-in-JS is that it just might not work for your particular application. If you're not using a front end framework like React or Vue, CSS-in-JS is probably not the right choice.

If you're in a situation where CSS-in-JS isn't a great fit, I highly recommend you check out Tailwind CSS. It is a utility first CSS framework that helps you build UI's rapidly. You don't get any of the benefits of CSS-in-JS but it may help you avoid some of the pitfalls of CSS.

Closing thoughts

As developers, our job is to solve problems using code. CSS-in-JS is a tool that helps us solve problems more efficiently and write code that should be easier to maintain.

If you've tried a CSS-in-JS solution and it didn't work out, that's cool too. Do what works best for you and your team.

Let me know if you have used CSS-in-JS and what problems it solved/caused for you!

Top comments (17)

Collapse
 
moopet profile image
Ben Sinclair

I don't know if I'm just one of those legions of knee-jerkers, but I think that CSS-in-JS is a terrible idea, pretty much for all the reasons you think it's good.

It's ok with components I guess, and they're all the rage among front-end blog posts this year, but we're getting farther and farther away from the idea of a simple, usable web. The dream of the semantic web died because of things like this, and the replacement doesn't add anything useful to the world. It seems to me like short-term solutions to fix things that aren't problems.

Think about it, can you remember every class name you used on your last project?

If you need to do this, I think you've got CSS wrong in the first place.

Collapse
 
thepaulmcbride profile image
Paul McBride

Hey Ben,

I have two things to add to your comment. Firstly, you're right, CSS in JS is a really great fit for the component model. It's also worth noting that that splitting a UI into small reusable components isn't a trend that is going away anytime soon. Not only is it great for simple blogs, it's nearly essential for larger more complicated apps. The semantic web is alive and well in the modern world of development. CSS in JS is a tool which ultimately ends up producing CSS that the browser interprets. If it is the right tool to solve a problem, why be so quick to shoot it down?

Secondly, I've been writing CSS in a professional capacity for the best part of a decade, so I don't think I've "got CSS wrong". CSS has limitations and choosing vanilla CSS over some other tool will have advantages and trade offs.

I guess my point is that as engineers, our job is to pick the best tool for the job. If that happens to be CSS, great, if not, pick something else that works. For me, recently, CSS in JS has been the right tool.

Collapse
 
tchaflich profile image
Thomas C. Haflich

The "day job" project I'm working on is made up of about two thousand non-library JavaScript files, with a component based structure. It's not bloat, just gigantic; those files are not just sitting around taking up space. Managing the JS alone is work, so keeping a separation of JS and CSS ended up taking up more management time than development time.

We ended up doing a minimal baseline CSS that's very rarely modified these days, and then going component-based for the rest of the styles. It turned out to be the right tool for the job. Development is fast and flexible and performance is good. Not to say there aren't drawbacks, but for this project they definitely are overshadowed by the benefits.

When I'm doing a small personal project, I end up usually defaulting to a purer CSS based approach and not going for inline styles, since they're not so difficult to manage.

Collapse
 
sinni800 profile image
sinni800

First of all, somehow this whole comment mostly read like how a politician would answer a question. That is, not actually provide insight, but talk meta. I'm not trying to be ad hominem, I'm just saying how it felt to me.

Splitting UI into small reusable components

From my experience it almost never actually works out like that. Write something reusable and next time it won't actually be usable like that.

One of your original points was that the browser only gets to interpret something it actually needs... Which brings me to the question: How does it save anything if now, instead of getting CSS rules by a .css file, it now gets CSS rules in a .js file? Also, how is your filtering logic on what CSS to actually present to the browser better than the browsers logic of parsing a CSS file, picking out what it actually needs?

I am inclined to trust the browser with being able to pick apart CSS that I wrote in a performant way (it's written in C++ too, and had hundreds of pairs of eyes on it in it's lifetime) rather than trusting me being able to present the right css to the browser at the right time. Also, I'm not sure but I assume it sets style attributes on the fly? Which would also not allow the browser to pre-parse and optimize CSS that was given to it in advance.

Why shoot it down when it's the right tool for the job?

Honestly, this way of phrasing it basically implies that it's a non-discussable given that it's the right tool and that critics are just trying to shoot down something they're ignorant about.

Wrote CSS for the better part of a decade, so I don't think "I've got CSS wrong"

I don't know, I've been writing CSS for like 13 years and while I do think I am quite proficient in it (by now), it doesn't mean this knowledge is a hard overwrite of everyone who disagrees with me. I mean, I disagree and think you've got CSS wrong, but more on the technical side. I elaborated above why.

Collapse
 
moopet profile image
Ben Sinclair

I guess I see people on Twitter demoing things using javascript objects to represent the style for (say) a button inside a widget. It's not usually doing anything more than you would using normal CSS, and I think it has a lot of drawbacks:

There are usually no consistent hooks so regular stylesheets will have a very difficult time affecting the way something looks. Why is that a problem? It's a problem for accessibility - if I want to add a custom stylesheet or use userstyles or anything, suddenly it's a whole lot harder if not impossible.

If I want to re-skin my site for a temporary christmas takeover, I'm out of luck, unless I import all the base styles and colours from a separate source, like a common javascript module or other kind of data store.

If you want to use the same component in multiple places, like in a sidebar, on a tablet, in a header, on someone's desktop with customised colour profiles, in print or as part of an app... you're either going to have to make new components or you're going to have to recreate media queries or the cascade, in javascript. I don't know why anyone would do that, but feel free to ELI5!

Collapse
 
benfluleck profile image
Benny Ogidan

Just have to say loved how you replied this question.

Collapse
 
yaser profile image
Yaser Al-Najjar

I don't believe that changing the nature of CSS would help writing more maintainable code.

And, that's what I love about the single file components in Vue for the reasons you specifically mentioned.

Collapse
 
vuild profile image
Vuild

I am generally weary of intermediate layers as bugs/entropy/updates whatever. Vanilla HTML/CSS/JS done well can be left for years. Can be hyper fast/simple clean (but usually we are rushed). Copy pasting a stylesheet & editing a few variables is as fast as it gets. Multiply the extra steps by 50 sites or something & it adds up.

I like CSS because it is a backstage dumpster where you can 'hide' things, no harm.

It would be very nice to have the features CSS in JS has however & I understand the use cases (if you are running a complex site with lots of ppl it is very good).

I think both have their place (this is probably now the controversial position).

Collapse
 
thepaulmcbride profile image
Paul McBride

Aren't all the tools we use to build websites essentially an intermediate layer? Unless you're writing byte code of course. I work at a product company so don't have the issue of setting up project after project, but I can see that becoming a pain if it's not automated.

You're totally right that both tools have their place though!

Collapse
 
vuild profile image
Vuild

Yes, they are all intermediates.

Imagine it like a sandwich. I like bread & cheese. Maybe a touch of butter. Fresh, warm organic bread. Simple, reliable. Focus on the cheese which was from cows that live in the mountains above the mosquito line.

Some people prefer a little more filling.
previews.123rf.com/images/goce/goc...

Each to their own (somewhere in between is usually good).

Collapse
 
marklai1998 profile image
Mark Lai

I agree with your reason
But I don't think the solution is always js since it already handle a lot of responsibility, separate CSS with js has its benefits like bundle size, performance, code test etc.....

I personally use CSS module in my project
Which I think is the best of both world

Collapse
 
thepaulmcbride profile image
Paul McBride

Hi Mark,

I totally agree that generating a separate CSS bundle from JS is an easy performance win. Thankfully, with most CSS in JS tools this is easy enough to do.

I had a chance to use CSS modules this weekend and they're really great!

Collapse
 
benfluleck profile image
Benny Ogidan

This is a nice summarized article thanks for that. Can I give a shout out to emotion.js which does almost exactly what styled-components does and occupies less space.

Before JS I used to involve myself with only CSS. After being introduced to styled-components I have found it impossible not to use on React projects. I still try to adhere to semantic-ui HTML principles as much as I possibly can when using styled-components and it provides excellent support for this.

Collapse
 
nepeckman profile image
nepeckman

This means the user ends up downloading fewer bytes of code and will have a quicker time to first paint. Great success.

I haven't done the benchmarks, but I feel like there's no way CSS-in-JS can be as quick as server rendered CSS. I'm not knocking the organizational benefits of CSS-in-JS, I love component architecture and am onboard with keeping related code in a central location. But from a performance standpoint, introducing a JavaScript step into the styling process seems like pure overhead. If there are any benchmarks on this, I'd love to see them.

Collapse
 
lkopacz profile image
Lindsey Kopacz

Damn, Paul! Really wanted to stir things up this weekend 😂

Collapse
 
thepaulmcbride profile image
Paul McBride

I'm both shocked and delighted with how it turned out!

Collapse
 
smonff profile image
🌌 Sébastien Feugère ☔

This is why SASS got created I guess.