loading...

Classical CSS vs CSS in JavaScript

ben profile image Ben Halpern ・1 min read

This has been a contentious debate with a windy path and lots of detours. What are the most important elements of this discussion and where do we stand now?

Discussion

pic
Editor guide
 

Classical! I think CSS is poorly misunderstand and slighted - when understood and well applied CSS can be a powerful tool or a frustrating after thought.

 

This is probably the best CSS description I've read. 👏🏼

 

I'm a convert to CSS-in-JS. The developer experience is really great. The cognitive overhead of keeping my component styles in separate files and switching between them was aggravating. It cost time and mental energy to keep track of everything. In the same way using a mouse is slow and distracting compared to keyboard shortcuts, CSS in separate files from JS components is slow and distracting compared to keeping it all together. It's still a separation of concerns, but the concern isn't style-vs-login; it's separation by component.

 

I had a doubt around nextjs style css in string literal. Is there any tooling suport for that? Like auto-complete, linter etc?

 

If you use styled-component or emotion with Next.js then you can use the VSCode styled-component extension

 

Vue.js and Svelte3 allows you to have scoped classical CSS inside of components.

 

In Angular too, and the absence of component scoped CSS in React is the only reason that would push me to use CSS-in-JS.

Yeah, React is all about Javascript (JSX, CSS IN JS).

Not really, CSS in JS is a community addition to react. By default there is only raw unscoped CSS if I'm not missing anything.

You can configure webpack to handle [.regex].css files as scoped.
In Create-React-App it's default if you name it .module.css that it's scoped.

 

My bias is that I don't use Javascript much, and I don't use componenty things like React at all.

But I strongly dislike CSS-in-JS, and disagree with anyone who says that it's a good separation of concerns.

I think that the CSS-in-JS movement came built on two trends.

First, the "framework" idea where CSS is used as shims for inline styles, with utility classes such as "large-text" or "padding-right-10" or whatever, and millions of non-semantic wrappers. These break any separation of content and presentation you might want by meaning you have to update your HTML every time you change anything about your appearance.

Second, the rise of node. People jumped aboard node more than previous languages/frameworks because they often already knew a lot of the language from classical Javascript, and because they saw an opportunity to re-make something in a relatively easy manner. Suddenly a million people without an original idea between them could put that they were the "maintainer" (or "creator" if they were being particularly shifty) of a package onto their next job application.

These together mean that the world is unapologetic about crossing style and semantic concerns or about needlessly remaking everything in JS.

When CSS-in-JS came around they didn't stop in their tracks and say, "hold up". It doesn't seem like a bad idea to them.

If I have a widget and I want to place it on a site in a main content area or a sidebar or a footer, I want it to get its styles from the cascade. CSS-in-JS simply can't do this, unless you import a bunch of common styles inside each widget. I've seen that advocated, and you know what? It's reinventing the cascade. Why import common styles in JS when you already have a way of doing it? One that won't break when your script throws an exception or fails to load?

I think, if anything, it should be called Style-in-JS, because it's not CSS. It doesn't use its own stylesheet and it avoids the cascade. Style-in-JS is OK. It's not exactly nice, but who hasn't written a hack somewhere that does more than a display: none toggle when there's no obvious easier way?

It's just, well, if I edit styles in my JS, I'd add a comment saying // @TODO: move these to a stylesheet.
And if I was going to keep CSS tied to JS, I'd at least keep it in a separate file.

 
 

Classical CSS. I tried CSS in JavaScript and I didn't like it. I am so use to connecting the HTML, CSS and JS separately.

 

Embedding CSS in Javascript makes a web app nearly unmaintainable on the long run. You start noticing it when you wonder where the hell that odd margin or background on an element came from, just to find out that it was set by some random script on a random created/mounted event. And what if you want to change the framework used by your frontend? If you keep JS and CSS separate, then it's easy to change the logic without breaking the style. Otherwise, be ready for crying.

A lot of issues in today's web development come from mixing templates, style and frontend logic all together. It took more than a decade to realize that mixing templates and backend code, like PHP or JSP would do, was a bad idea that led to unmaintainable and undebuggable code. It'll probably take the world one more decade to realize that mixing styles, logic and templates is an awfully bad idea for the exact same reasons: logic layer and presentation layer ought to ALWAYS be separate.

 

I ❤️ CSS-in-JS because it's so easy to use (although I may be biased because I'm very used to it at this point). I use it in all my side projects if I can.

It's not perfect though, and it can cause performance problems depending on what you're trying to render. There are some people at Atlassian who are trying to solve some of these performance issues with compiled-css-in-js so it will be interesting to see where that goes.

 

It's gotta be a split. The entire theme can't be done inside JS components. I love something like Tailwinds in the template and then CSS in js for the components. It's the best way I know to stop a stylesheets' persistent growth.

 

Classic css feels like cubersome for me. But it does give me benefit of using css classes anywhere. I'm not into CSS-IN-JS but I just hope that CSS can be as strongly typed stylesheet as Any other languages it would be.

OFF-TOPIC: Still waiting for FLUTTER VS REACT NATIVE Post. That's the most talkative Mobile framework on the web. Well of course, my profile pic says it all.

 

CSS scoped is a nice shortcut to reducing complications, and it is still CSS in HTML.

In the end, I still prefer CSS in HTML for SEO purposes, perhaps still with Webpack and mini-css-extract-plugin.

 

CSS in JS seems like just another iteration of how to complicate software development. There are also performance issues and compilation issues. My school of thought is "If it's not broke, don't fix it". CSS is a unique language in and of itself. It has expanded a lot in recent years first with animations and now with vars, additional features to forms, cool pseudo selectors and functions like mathematical calculations on vals. I honestly don't think there is a need to change how I program unless the library or framework I'm using is better served by using CSS in js, such as React (which is built for this).

 

I have tried many ways of doing CSS-in-JS, here is what worked and what didn't for me:

  • Next.js styled-jsx: uses real CSS, moves declarations to a template literal, but you still have to do class name mapping yourself. Note: 2/5
  • Styled-components : uses real CSS, defines special (styled) components only for design. Good but makes a lot of boilerplate to override some things locally. 3/5.
  • Styled System (ThemeUI, ChakraUI): uses React props and a central theme definition. Not quite CSS, has shorthands (which helps, less code to type) in addition to camelCase CSS properties, but allows definition of a design system that resolves to CSS, easy to do local overrides. Perfect for serious long-term projects. 4/5
 

I find scoped css awesome for making webapps ( like css modules or svelte's approach)

But currently we are making shopify apps which require heavy customization, so we find css in js, better for these kinds of projects.

 

Anything but classical css.

CSS works for tiny projects, like a single component. As the thing grows it will break down.

I know there are ways to work with CSS that mitigate those problems, but I never found any way to actually work.

By moving the CSS into the code you make the code aware of the CSS and that allows refactoring and dead code elimination on a different level.

 

My thoughts are anything that gets us away from a DSL, is the right direction.
Case in point, ever try to refactor and clean up a large project's Css across 20 or more files each with hundreds of lines?

Painless Maintenance: Never go on a hunt for CSS affecting your components ever again.

 

The arguments for separating CSS from JS are, in my experience, misguided.

You will hear that putting your styles in a style sheet is "separation of concerns". But I don't think that's quite right.

If your styles are concerned with your UI code, then they belong together.

However, you can achieve this in many ways. With styled-components, or with CSS classNames and having many individual stylesheets for each component of your code.

I find that styled-components offer the best mix of both re-usability (via composition) and clarity. I love that I do not have to go searching for where my styles are defined and worrying about how they are somehow inherited from other places. The structure is clearer.

But, as with all things, the caveat is: do what feels natural to you, what solves your problem, and what makes the most sense given your technical stack and direction.

 

Performance, CSS in JS inherently adds weight to your build and commonly introduces caching issues. In addition we as developers must remember who is the most important person when building Apps. It's the User :) imo CSS in JS is all for the developer and making their life easier, not the user.

 

As someone who has been building for the web for 2 decades, I fail to see how suddenly jamming my CSS inside my JS will solve any problems I didn't have.
Heck, I don't even use component scoping.
A proper design system will prevent any management problems.
I guess I treat JS and CSS as equals, where my JS should produce HTML that will display the way my CSS dictates.

 

I don't think classical CSS gets enough credit. It's very powerful. Even as a very basic example, I think it's very cool that even to get a simple hover effect, it's as simple as appending ":hover" to the class rule. Anyone can probably look at that css rule and understand what it does, or at least understand it quicker than css-in-js code. Personal feeling is that's easier than writing the mouseover javascript event to add the style. I think if more people stayed up to date with MDN and CSS-tricks, they'd give classical (well, I call it advanced) css. I call it advanced because the native css is constantly improving and catching up to what some of the pre-compilers can do.

I think if there are certain css properties that need to be controlled based on application data, then css-in-js makes sense, but only for those cases. I'm sure my comment will get mixed reviews, but I'm just speaking from experience.

 

With Vue.js, classical CSS is quite nice thanks to the built-in scoped CSS support. A lot of the caveats of classical CSS are due to the fact that it's all global.

That being said, I work on different projects using different frameworks. Some use Vue.js, some React.js, some Nuxt.js, some plain old vanilla or server-side rendered templates. What I dislike about css-in-js is that it's pretty much a react-only solution. I mostly just use tailwind where I can keep the same paradigm across projects. No need to relearn CSS every time I pick a different tool :)

 

My friend suggested we could use something like bonsaicss.com/ so that we can add utility-based styling right inside the React component code, instead of just external CSS or JS object-based styling. I think it makes sense in some cases.

 

I'm completely happy with Classical CSS along with BEM naming conventions, which fits for most of the use case website, application development, and provides significant freedom like normal CSS, no need to tool supports.

 

As a vue developer let me ask.

What are you talking about?

 

Scoped styles with some global class /var all the way! Technically it's CSS in Js I guess... but written in style tags.

Easy to target, easy to name, easy to find, one syntax. Best of both worlds!

 

Some scoped CSS, Vue allows it by default, in React I would use CSS Modules.

 

I've used CSS-in-JS a couple of times, but personally I still prefer classical CSS (especially the way Vue.js and Svelte3 are using it)