DEV Community

Cover image for The ugly part of CSS-in-JS
Andreas Sander
Andreas Sander

Posted on

The ugly part of CSS-in-JS

One often-overlooked aspect of CSS-in-JS is its "dark side"—the "JS" part. What does this mean? Essentially, when you're writing your styles within JavaScript, you expose yourself to the quirks and intricacies of JS itself.

The Issue Illustrated

Consider the following example:

You might notice that the styles defined in IBreakStyles aren't applied as expected. Digging into the element with your development tools reveals a complete absence of styles.

The Root Cause

The culprit is a stray closing curly bracket within the template literal:

const IBreakStyles = styled.p`
  padding: ${({ $count }) => $count + "px"}}; /* <-- The offender */
  color: red;
  background-color: blue;
`;
Enter fullscreen mode Exit fullscreen mode

What happens is that the CSS-in-JS library (in this case, styled-components) interprets the template literal in a specific way. This leads to parsing the CSS via JavaScript, and the stray curly bracket disrupts the intended behavior—likely closing some parent block in the JS logic.

The Silent Problem

The real issue is the absence of any alert mechanism: no errors are thrown, and no red squiggly lines appear in your editor to warn you. If you're fortunate, your editor's CSS-in-JS tooling might catch this, but that's not a guarantee.

A Thought to Ponder

Given these complexities, it's worth questioning if a separation of concerns—CSS in CSS files and JS in JS files—might not be a more foolproof approach, much like the "good old times."

Best regards,

Andi

Top comments (14)

Collapse
 
efpage profile image
Eckehard • Edited

CSS itself has some conceptual issues and limitations. If you use it the way it was initially intended, it works pretty straightforward. But some solutions try to overcome this limitations. If that means, that each element is marked with a classname behind the scenes, this will possibly bloat your files and cause more problems than it solves.

Any solution should be minimally invasive. If you just need some very conventional styling, it should allow to use the "good old solutions" and schould not affect your workflow.

Collapse
 
andi1984 profile image
Andreas Sander

I agree 100%!

But some solutions try to overcome this limitations.

I also see this point you made and there is definitely also a good/"beautiful" part of CSS-in-JS. But it is as you said: Choose your tools wisely for the work you want to do and the goals you want to achieve.

Collapse
 
moopet profile image
Ben Sinclair

CSS-in-JS comes with a lot of problems, and even "fixing" it with things like smarter linters doesn't get around the fact that you're painting yourself into a corner.

I think it would be better to keep the styles separate.

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

I don't really like the idea of writing CSS as strings within JS only for those to then get parsed into some internal representation and serialised back into CSS code.

In my opinion, it makes much more sense to write styles directly in the form of javascript code and let the browser take care of checking and reporting whether the syntax is all correct. Nested JS objects can get relatively close to CSS both in syntax and in functionality.

Ideally I'd want to write something like

const my_styles = css({
   padding = CSS.px(whatever),
   color = 'red',
   backgroundColor = 'blue'
})
Enter fullscreen mode Exit fullscreen mode
Collapse
 
artxe2 profile image
Yeom suyun

I don't really like styled-components, but I think the examples are too limited.
However, with a few improvements, I think libraries that use templates like styled-components could also warn about typos, just like vanilla-extract does.

Collapse
 
andi1984 profile image
Andreas Sander

@artxe2 I agree and partly they do as part of editor extensions (cf. @joelbonetr comment below). But I think – although VSCode is pretty much defacto standard editor nowadays – they can not assume that the user has their extension installed or even using another editor/IDE where there is no extension available.

I would personally like to see – at least – a warning in the dev console or something similar. Thus I agree 100% with you!

Collapse
 
joelbonetr profile image
JoelBonetR 🥇 • Edited

This is a concept issue. If we get to have all capabilities pre-installed and available, the IDE would be super slow and inconvenient overall. Allow me to drill down the topic:

The language I use most is JS/TS, there's native support in VSCode so it's not much big of a deal, but lets dig deep.

In some projects I use NX to handle a monorepo, for which I need this extension.

In most projects that implement React -or Next JS for the record- I use styled-components as it simplifies the smart-dumb architecture and it has certain benefits I love, in this situation I need this extension

I may use RapidAPI extension to test the endpoints I code or third party ones when doing an integration.

In certain projects in which I handle the data as well I might use PGAdmin sometimes but also SQLTools extension depending on the situation.

In all use-cases I'm using GitLens to work with git faster and better.

But then... then I switch to C++ sometimes, for which I need 4 extensions, installed through the C/C++ extension pack

I might switch to Python for other tasks, for which I need the python extensions and the Jupyter ones .

I have more extensions installed but the key here is that I only enable those that I need at that given moment, otherwise certain extensions can cause conflicts between each other.

From the PoV of JS, a template string is just... a string.

You'd love to see built-in code analysis on template strings for styled-components but another dev might work on email templating and they would love to see spell checking capabilities built-in template strings, and probably html color codes, just to add an example. In which case you may install the Styled-Components extension and the other would love the ES6-string extension.

And that's the neat part of VSCode, that you can install or develop extensions to fill the gaps and comply with your needs! 😁 But having everything built-in by default would be quite counter-productive because certain parts will always be bloatware -software that's pre-installed but the user will never use-, messing up the dev experience for everyone.

Hope it helps on understanding the big picture 😃

Thread Thread
 
andi1984 profile image
Andreas Sander

You're right about that and VSCode Profiles are very helpful also in that regard to have different profiles maybe for different people, but also the suggested extensions you can define for every particular repo.

Still – call me an old guy or something :) – I think we can not assume also nowadays that users have those tools at their hand or probably they just don't know about them. That's why I would love to see at least some glimpse of a warning either on the CLI (if it can be detected at compile time) or a warning in the client (if it only gets detected at runtime). I admit that a console.warn would not be optimal, but at least as a dev checking your project with devtools, you will get an idea of what is wrong.

But as you said, there is probably a tool, extension/plugin for it to include into your IDE and you're safe regarding such issues.

Collapse
 
redbar0n profile image
Magne • Edited

Template literals may be the culprit of the problem here. There are some CSS-in-JS libraries that don't use template literals, and provide type safety (squiggly lines).

Check out Tamagui.dev for best-in-class CSS-in-JS experience for React and React Native (works crossplatform, with SSR!), where styles are pre-computed at build time, so there's no JS to change styling at runtime. It also has type-safe styles.

Alternatively try Panda CSS, which is also build time CSS-in-JS (the successor to Chakra UI), also has type-safe styles, and works across more rendering libraries, like Qwik.

Collapse
 
andi1984 profile image
Andreas Sander

@redbar0n Thanks for all those infos. I haven't heard about those and it is definitely interesting to see compile vs. runtime discussion. I will have a look at those mentioned libs and I assume those are also valuable to other readers of the article. Many thanks!

Collapse
 
joelbonetr profile image
JoelBonetR 🥇

Just install the Styled Components plugin in VSCode and it will warn you.

Collapse
 
andi1984 profile image
Andreas Sander

@joelbonetr Yes, I just did the same after I faced this issue in one of my projects. For completeness this is the VSCode extension we speak about:

marketplace.visualstudio.com/items...

Collapse
 
mflorida profile image
Mark M. Florida

CSS-in-JS is an anti-pattern, especially as implemented with Styled Components.

CSS modules are what Styled Components wishes it was. (they were?)

😎

Collapse
 
mattkenefick profile image
Matt Kenefick

This article could just say "The ugly part of CSS-in-JS is CSS in JS." And that's it.

Don't put CSS in JS.