DEV Community

Classical CSS vs CSS in JavaScript

Ben Halpern on June 03, 2020

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?

Collapse
 
sirseanofloxley profile image
Sean Allin Newell

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.

Collapse
 
sarahk profile image
Sarah

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

Collapse
 
tvanantwerp profile image
Tom VanAntwerp

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.

Collapse
 
kokaneka profile image
kapeel kokane

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

Collapse
 
shakib609 profile image
Shakib Hossain

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

Collapse
 
9zemian5 profile image
Oleksandr Demian

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

Collapse
 
korbraan profile image
Cédric Rémond

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.

Thread Thread
 
9zemian5 profile image
Oleksandr Demian

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

Thread Thread
 
korbraan profile image
Cédric Rémond

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.

Thread Thread
 
supportic profile image
Supportic

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.

Collapse
 
moopet profile image
Ben Sinclair

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.

Collapse
 
bizzibody profile image
Ian bradbury

Well said.

Collapse
 
angelyoung24 profile image
Angel Young

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.

Collapse
 
blacklight profile image
Fabio Manganiello • Edited

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.

Collapse
 
emma profile image
Emma Goto 🍙

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.

Collapse
 
vinceramces profile image
Vince Ramces Oliveros • Edited

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.

Collapse
 
gdouglas profile image
Graham Douglas

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.

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt • Edited

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.

Collapse
 
jrohatiner profile image
Judith

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).

Collapse
 
franky47 profile image
François Best • Edited

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
Collapse
 
gpmcadam profile image
Gary McAdam • Edited

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.

Collapse
 
odalrick profile image
Ulrik Långström

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.

Collapse
 
ctannerweb profile image
Cory Tanner

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.

Collapse
 
jwp profile image
John Peters • Edited

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.

Collapse
 
itsjzt profile image
Saurabh Sharma

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.

Collapse
 
rajajaganathan profile image
Raja Jaganathan

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.

Collapse
 
nirlanka profile image
Nir Lanka ニル

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.

Collapse
 
dkruythoff profile image
Darius Kruythoff

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.

Collapse
 
richardeschloss profile image
Richard Schloss • Edited

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.

Collapse
 
michi profile image
Michael Z

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 :)

Collapse
 
fayaz profile image
Fayaz Ahmed

As a vue developer let me ask.

What are you talking about?

Collapse
 
perpetualwar profile image
Srđan Međo

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

Collapse
 
etienneburdet profile image
Etienne Burdet

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!

Collapse
 
9zemian5 profile image
Oleksandr Demian

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)