DEV Community

loading...

The one about CSS vs CSS in JS

adancarrasco profile image Adán Carrasco ・5 min read

An interesting topic when doing Web Development and nowadays not only Web Development is choosing how your Application will be styled. In today's post I will be comparing some of the pros and cons in CSS as well as in CSS in JS.
What is CSS

What is CSS?

Cascading Style Sheets, is a technique to change the look and feel of your Web App, you do it using selectors (what rules you want your styled to be applied to), selectors can be via created HTML tags, ids, CSS classes, etc; once you have your selector you can set different props, as font color, background color, font family, etc.

One of the main advantages of CSS is that you can change the look and feel of many elements at once with a selector.

/* This rule will set the font-size and font-color 
as 12 pixels and orange to all the paragraphs in our whole application */
p {
  font-size: 12px;
  color: orange;
}

Now, what is CSS in JS?

Is nothing more that applying styling to your Components using CSS props via JavaScript, how this is possible? There are many ways, one it's adding inline styles (props) to your component.

// This will render a component (build with React) with the same 
// props as we defined in the previous code
const MyComponent = props => (
  <p style={{fontSize: '12px', color: 'orange'}}>hello</p>
)

Another way to do it is using a library as EmotionJS that will generate some CSS classes for you and will inject them into your Components.

// This will render a Styled Component with the same props 
// as the two previous examples

const MyComponent = props => (
  <MyStyledP {...props}>hello</MyStyledP>
)

const MyStyledP = styled.div`
  font-size: 12px;
  color: orange;
`

One of the main advantages of CSS in JS is that you have only the CSS your component needs, preventing any overrides and making it usable as a standalone piece of code.

CSS Pros

CSS

Pros

The standard to change the look and feel in Web Development

In the old days was really hard to keep the same color for different components and was really easy to have a lot of duplicated CSS (when multiple developers were working in the same project). This was because there was no variables to persist non changing values and there was no easy way to reuse rules. Then it became the standard with the war of different browsers as Internet Explorer, Mozilla and then Chrome.

Can use preprocessors

Later preprocessors as LESS and SASS came to make the use of variables and reusing code possible, you could easily nest your inner selectors being wrapped by the main CSS class and also add some variables to it.

Good performance

Since it's and became the standard it's really easy for Web browsers to apply the styles, they have been doing it all the time. Also, the output code applied to the HTML elements is only the needed even tough the CSS code can contain non needed and non used code.

Applying a CSS theme/skin is easy

If you follow a good naming for your selectors and the use of namespacing, will be really easy to come with a different theme and apply it to your Web App.

Cons

Naming is hard, unless you follow BEM or similar

As CSS became the standard, patterns to apply a good CSS styling became popular, one of those is BEM (Blocks, Elements and Modifiers), following this out class name generated will be something like:

/* block--element-modifier */
.button--state-success {
  /* here you put your css rules */
}

Easily to commit typos and override props, which leads to use !important in some cases

There's a high possibility that as developers we will have typos in our code, and there's a high possibility that someone will redefine an existing CSS class, and the one at the end will be the winner, unless someone uses !important which is really nasty.

Dead code risk (dead rules) and hard to maintain

If in the Dev Team there's not strict rule on removing unused code more and more CSS will be created, and depending on the way you use to create more CSS files the harder will be to detect where you need to cut/remove the unused code, this also makes it hard to maintain

Need to worry about compatibility with browser's CSS extensions

If you are managing CSS manually you need to worry about different CSS extensions as: -moz, -webkit, -ms

CSS in JS

CSS in JS Pros

Pros

Uses CSS which is the standard

So you don't need to learn anything new to style your components since you've been using CSS all the time.

No need to worry about naming or overriding of props

You don't need to worry about overrides because the CSS used in your component lives in your component only.

Using frameworks as EmotionJS generates browser specific extensions as -webkit, -moz, etc

When using pure CSS you need to worry about the specific browser extensions, however when using this pattern, the library does that for you, generating any of them, this is a relief because you know that as long as the library is supported by the browser, the rules will be available.

Easy to maintain

As the CSS is in the component only it's easy to remove the CSS you no longer need. Also if your component needs some specifics you can modify those specifics depending on the use case passing the variants as props. And the best, if the component is no longer needed you only remove it and that's it. NO SIDE EFFECTS!

Cons

Performance may be affected because of the computation to inject the CSS

Since every component has its own CSS rules the JS bundle can easily grow, and in the other hand the JS needs to be processed by the browser to apply the CSS while in the other hand (using CSS only) the CSS is ready almost at the same time as the HTML components.

Hard to reuse rules

The rules applied to your components are only living in your components, this makes it really hard to reuse the rules you apply to your component to other components. However, if you are using this pattern, doesn't necessarily mean that you cannot use CSS, so mixing both approaches can solve this issue. :checkmark:

Applying some themes, skins may be more complicated but can be generated from a JSON which could be as

Applying themes when using this technique at some point could be harder compared to using CSS only, however if you have a good architecture and a good definition on how you want to use your CSS in JS you can easily spread the props from the parent component to the most inner component. Plus you can use some of the CSS variables advantages. 😉

Is it still CSS? Cascading is lost

IMO the most important paint point is that Cascading is lost and this means you cannot have a CSS in JS that will apply to a nested component, well you can, but you will be violating the principle of this technique which is independence in your components. This loss makes a lot of noise when deciding wether to use or not this technique.

Conclusion

As a personal conclusion I don't think there's a best option, it will depend in your project needs. However, nowadays I'm combining the two approaches making one stronger when the other is weak. I can use CSS variables and apply it to my Components and isolate in the Components what needs to be isolated, just as I would do it using namespacing.

When would you use one or the other?

Thanks for reading!

Discussion

pic
Editor guide
Collapse
colewalker profile image
Cole Walker

I much prefer Scss stylesheets to css in JS. You get basically everything you could need out of Javascript, but with better reusability and performance. Additionally, it keeps the cascade which is good for learning and can easily be used to your advantage.

Collapse
mattwaler profile image
Matt Waler

The cascade is only as advantageous as your weakest developer on the project, or the scale / scope of the project itself. It will almost always become a burden as the codebase grows. This is really the only reason I prefer CSS modules or solutions like TailwindCSS.

Collapse
moopet profile image
Ben Sinclair

I see Tailwind as more of a problem in search of an audience than a solution in search of a problem.

Thread Thread
mattwaler profile image
Matt Waler

Tailwind has already found an audience (21,000 stars on github) and it's definitely solving a problem (css scaling indefinitely with project scope) that I've experienced in almost every large-scale project. I'm sure you have experienced it too.

Many big-scale companies are already using it with great success.

Here are a bunch of articles talking about the problems it solves as well

Hopefully it can open your mind up a bit to the possibilities and advantages (and disadvantages, I'm not pretending there aren't any)!

Thread Thread
moopet profile image
Ben Sinclair

I'm fairly sure I'm never going to like Tailwind. When I say it's in search of an audience, I mean it pretty much exists because it was low hanging fruit, a quick way to make something popular. People like it, yes, but people like mayonnaise too, so people can be wrong.

Thread Thread
mattwaler profile image
Matt Waler

The only thing you've brought to this discussion is that you don't like Tailwind. That is entirely fine, but I would urge you in general to push past your initial preferences and distastes to truly see the pros and cons of new approachs and tools. Otherwise, you may never find out something new and exciting that changes your way of thinking!

Thread Thread
moopet profile image
Ben Sinclair

I know what you're saying. My distaste for Tailwind, however, isn't an "initial" reaction, and it's not specific to Tailwind. I've been aware of variations on these ideas for years, and think they're a very bad direction for development to go.

I'm drawing the comparison between utility classes in general and the idea of CSS-in-JS, because I think that it's a similar fad, and that - barring some kind of AI revolution - it's going to cause a lot more problems as time goes by.

Maybe a better example would be comparing either to the use of tables for layout. You can see pros and cons for that, too - but people aren't making the case for switching to tables in 2020.

Thread Thread
mattwaler profile image
Matt Waler

I would love to continue this discussion, IF you could bring some real actual examples of where these tools caused problems down the line, and how on earth they even remotely compare to CSS tables. I truly think you lack a full understanding of both CSS-in-JS and Tailwind, and you use metaphors and inaccurate comparisons to hide that fact.

Thread Thread
moopet profile image
Ben Sinclair

The problems with non-semantic frameworks are pretty well-documented. Having a set of utility classes like big 10pxpadding widemargin blacktext otherspecificthing in your HTML is not better than using inline styles. If your website has - for example - a Christmas takeover where things are restyled to be red and green and festive, you're in for a long, boring job rewriting all your components.

Thread Thread
mattwaler profile image
Matt Waler

They are nothing like inline styles. With inline styles, there are 0 constraints and 0 responsive options. With utilities classes, you can create a defined set of classes, some of which can be responsive like sm:text-center and so on. Also, I would MUCH rather undo a "christmas takeover" by creating new utilities called christmas-{blank} that I could remove later versus having to comb through semantic CSS and revert.

Thread Thread
adancarrasco profile image
Adán Carrasco Author

In my current use case I'm mixing both approaches, using Cascading for the things that can be cascaded and CSS in JS for the things that are capable for that. Let's see where it will end. I will keep you guys posted. :)

Collapse
peck_arthur profile image
Arthur Peck

I love styled-components in react!

Collapse
icyjoseph profile image
Joseph

CSS in JS when using CSS syntax, and injection of style tags, as in styled components, is great to take advantage of components hiding implementation details. When using JSX for example, the style becomes part of the JSX declaration!

As a consumer of a stylesheet API you gain tremendously over having to learn a map (class -> node) where, for instance, all the decisions made by the creator matter. Of course one can churn out wrapped components with already assigned class names, but that's just duplication of both CSS and JSX.

Collapse
moopet profile image
Ben Sinclair

I understand how CSS in JS could be useful when creating an app like a spreadsheet or something - the same way I understand why people like non-semantic "utility" frameworks.

For use in general websites and apps I think it has no real redeeming qualities, because of the cascade. It's not just noise, it's like throwing away the entire point of stylesheets.

I can't think of any time I'd want to take a component and drop it onto another site with a completely different appearance and not want to style it to fit in. With CSS, and with sensible semantics, that's no issue; with CSS-in-JS it's more duplication of effort.

It also reduces your ability to drop the same component into different parts of the site. A component fitting in the header might display differently to one in a sidebar, for instance, and might behave differently when the browser resized or changed orientation or switched fro LTR to RTL reading directions. Managing that in JS is going to be a pain in the butt, but I expect people will come out with some over-engineered solution if they haven't already in order to reinvent the wheel.

Collapse
pontakornth profile image
pontakornth

Without styled system like Chakra UI or Rebass, I don't really like CSS-in-JS much. I prefer PostCSS with Tailwind.

Collapse
adancarrasco profile image
Adán Carrasco Author

Didn't know about Rebass. Really cool component libraries! Thanks for sharing!

In my current use case I'm mixing both approaches, using Cascading for the things that can be cascaded and CSS in JS for the things that are capable for that.

Collapse
mattwaler profile image