
Why I Write CSS in JavaScript - bpierre
https://mxstbr.com/thoughts/css-in-js/
======
exogen
Imagine a programming language that only had global variables.

You have to carefully name your variables using complicated conventions in
order to avoid any conflicts or unexpected behavior.

Even your functions don't have local variables; there is no lexical scoping.
Any function can overwrite or mutate what any other function is doing inside.
There is no real encapsulation.

After you've done this perfectly, your application gets bigger and you start
wanting to reuse third-party modules made by other developers, because they've
already solved some of your problems.

Uh-oh: they didn't follow exactly the same conventions, and now things
conflict. Or their variable names _were_ perfectly unique in their own code
base but not when combined with yours (or when combined with several other
third-party modules).

This language is CSS and is why people are so fed up with selectors. Even
"scoped" selectors really aren't lexically scoped in the sense that other
languages handle scoping... it's still just another naming convention hack.

I use CSS-in-JS because CSS wasn't designed to be a language that survives
attempts at modularization, third-party code sharing, etc. No sane programming
language attempting this would only have global variables. So, we throw out
the selectors part of CSS and keep the rest, at least for now.

Nobody using CSS-in-JS thinks this is an ideal situation. Nobody wakes up
thinking, "oh my god, I need to put my CSS in my JS, it would be perfect."
We're just trying to deal with the hand that's been dealt.

~~~
pmlnr
CSS is not a programming language, and it shouldn't be viewed or compared as
one.

It has different functionalities.

~~~
gaastonsr
CSS is a tool used by web developers to style their websites.

Whether technically it's a programming language or not is tangential.

~~~
jandrese
People implement Doom in CSS. It's clearly more than just some style notes for
the browser.

~~~
gmanley
I think you may be confusing that with something else. You can't create a
complex game with just CSS. I'd love to be wrong but provide a link.

~~~
jandrese
[https://codepen.io/chrissimmons/pen/bqBabr](https://codepen.io/chrissimmons/pen/bqBabr)

It's off brand, but the technology is roughly the same.

Another game: [https://thenextweb.com/dd/2018/05/08/some-madman-built-a-
mar...](https://thenextweb.com/dd/2018/05/08/some-madman-built-a-mario-kart-
clone-in-pure-css/)

~~~
gmanley
The first one looks like a big part of the functionality is from the
JavaScript file. It's crashing my iPhone so I'm having trouble digging into it
too much. The second link, however, does seem to be done in pure css.
Impressive! Thank you for the links. I stand corrected.

------
LocalPCGuy
I understand the "pit of success" idea, particularly when it comes to more
junior devs. But I don't necessarily agree that you need stringent processes
to get most of the gains you cite from using something like SCSS or even
regular CSS these days. It's really easier than ever.

1- append only? No, each module/feature/widget gets its own CSS file, imported
to the main app CSS file. Delete the widget? Delete the file.

2- Specificity issues? Never use IDs, stop using tag names and simple classes
and adopt a simple naming structure (doesn't have to be BEM, it could
literally be ".widgetName-header")

Since I adopted those 2, I've almost never had dead CSS from deleting features
or collisions in my CSS. I do still have a small base set of styles that are
shared but it's small enough to be easily manageable.

3- dynamic properties? CSS variables. Not an option? Child classes that apply
the dynamic styles serve most use cases. Truly dynamic styles are rare, in my
experience.

I'm still keeping an open mind about the possibilities, but my strong opinion
(weakly held) is that I still don't see CSS-in-JS as more of a bandaid for
people that like CSS and (for many, not all) those that don't have an in-depth
understanding of it.

~~~
qudat
> Delete the widget? Delete the file.

This rarely happens. I would argue that creating an automated system to
enforce "rules" should be favored over forcing every developer to know the
rules and abides by them.

It is much easier to understand the relationship between css and js when the
css is just a js variable.

Having built many large applications using the CSS file method, css modules,
each widget gets its own file, co-locating css files with the js, I much
prefer using `styled-components`. It provides a ton of flexibility, it opens
doors for dynamic css by leveraging js (the hacks I've seen, had to write to
get css dynamic is astounding), and I don't have to look very far to see how
it's being used because the CSS is literally attached to the component I'm
using. All I do in VSCode is cmd+click and bam, I can see the CSS for this
component. There's no need for naming convention, there's no worry about
global css variables getting into your styles, and there's no digging around
looking for css that might be influencing your component. The best part for me
is: when I delete the component, the CSS is gone as well. There's no thought
put into scouring the FS to find lingering CSS that used to be used.

I love `styled-components` and most of the designers I work with also enjoy
it.

~~~
LocalPCGuy
Why wouldn't the CSS file be deleted? It should be co-located with the widget,
so you just delete the entire widget folder.

~~~
ravenstine
Yeah, it's really not hard to delete a CSS file. People really are _that lazy_
, but that's on them, not the technology.

~~~
exogen
Nobody thinks it's hard to delete a file.

It's hard to know when you can delete a _rule_. Are you positive that all the
rules in your component's CSS file _only_ affect that component? Then great,
delete the whole file.

What about the individual rules within that file? How do you know whether your
app is still rendering any components with the `fancy` modifier anymore? Keep
in mind any JS on the page could be be dynamically toggling the `fancy` class,
including in very rare circumstances, including from dynamic data that might
bring the string "fancy" with it so that you can't just grep your codebase for
it. Is it safe to delete the `fancy` rule?

Another problem is that even BEM admits that sometimes nested selectors are
necessary. It's right there in the BEM FAQ: "While in general BEM recommends
avoiding nested selectors, in this case they are reasonable."

Sometimes you need your button to look a certain way when it's inside a nav
menu item.

So what's the solution? Either a nested selector (targeting both the nav item
and the button) or a new modifier on your button, like `is-in-nav-item`.

Eventually your app changes and you're not rendering any buttons in nav items
anymore. Maybe nav items don't even exist anymore and you at least remembered
to delete _those_. Are you also going to remember all the places in your code
you need to track down to delete these obsolete nested selectors/modifiers? Or
is there just going to be dead code now?

What if the selector is slightly more general, and you're not sure if it's
targeting other things as well? Are you confident that you won't break
anything else? CSS selectors are effectively global. Anything could be
secretly relying on the styles that a selector applies.

That is the problem. Not deleting a file. Your individual component CSS files
are now the "append-only" stylesheets, not necessarily the whole combined
stylesheet.

~~~
LocalPCGuy
> Are you positive that all the rules in your component's CSS file only affect
> that component?

Absolutely

------
Yabood
We built a relatively large social media management platform, and for one of
our major features (a streams page that shows social media activities from
different sources), we put a lot of our css in JS including all the logic for
stream sizing/resizing and page responsiveness. I can honestly say that this
approach is terrible. It is a maintenance nightmare. Even the smallest changes
require a ton of time. We're now rebuilding the page from the ground up
because it has gotten so messy, no one on the team is interested in touching
it.

~~~
abderrahmane
Why can't we see more of these stories surfacing on the internet. All I see
when I search for CSS-in-JS on google is how, CSS-in-JS is so great.

Why don't we have more : "We tried it, it is the worst, especially for
products which lifespan is more than two months"

~~~
black-alert
> Why don't we have more : "We tried it, it is the worst, especially for
> products which lifespan is more than two months"

Because that last sentence is just rubbish, CSS in JS is great. I'm using it
for large projects already 4 years. If your experience is bad you must be
doing something wrong. CSS in JS is almost the same as working with (S)CSS,
except for extra power to control dynamic elements without having to juggle
with classnames.

~~~
YorickPeterse
Clearly when somebody has a bad experience, they are just doing it wrong.

Or perhaps there's something to it, and the idea is not as good as one might
claim it to be.

~~~
pvorb
Or they are solving other problems and that's the reason why one believes a
solution is bad and another one thinks it's the best.

------
jmull
I'm unconvinced.

For one thing, it's not CSS in Javascript... there's no cascade and no sheet,
so it's just "styles in Javascript". (And, actually, this article is only
about a specific implementation.)

The benefits listed are:

\- "confidence" \- but I think that's a matter of understanding and mastering
the tool, whether it's CSS or this library. As the co-creator of "styled-
components" the author is no doubt a master of it. For for the general
developer, perhaps a roughly equal effort would provide a similar level of
mastery in each. So why not invest in the standard?

"Painless Maintenance" \- I would have to use it deeply before I could say too
much about this. But I would guess that the danger of creating spaghetti code
and a spaghetti of .css are pretty much the same and have the same root
causes.

"Enhanced Teamwork" \- I don't see the connection here. The discussion in this
section seems to be about mastery of the tools again. The team can learn how
to manage styles though CSS-based techniques or they can learn through
techniques based on coding Javascript and the capabilities of this library.

Not that CSS doesn't have its issues. IMO, it's too low-level to use directly
for many cases. There are two main problems: (1) missing the tools to manage
complexity, like scoping, variables, and modules. (2) allows you a lot of
freedom to do bad things. But there are libraries that address these that
don't throw out the fundamental design of CSS, as styles-in-code does.

To me it seems like a better approach to build on CSS to address its
weaknesses rather than throw it out.

The design of CSS itself came out the recognition that the tight coupling of
style and content has drawbacks, and this is signing back up for those
drawbacks. And you better neatly divide your presentation code from your
business logic code and data access code or you'll get all that coupled
tightly as well.

I'm not dismissing this out-of-hand -- I haven't dug into styles-in-code
approach so I don't have a deep understanding of it.

But I'm not convinced it's worth the time to look more closely at it. Really,
not even close.

~~~
jancsika
> "Painless Maintenance" \- I would have to use it deeply before I could say
> too much about this. But I would guess that the danger of creating spaghetti
> code and a spaghetti of .css are pretty much the same and have the same root
> causes.

But as you pointed out, there is no cascade and no sheet. The styles
apparently just apply to the stuff they are near in the code. No twisted logic
to unwind, hence no spaghetti.

The potential problem I _could_ see is that changes which would have been easy
with a cascade would require lots of changes to copypasta in this approach.
Like, "take the spinach out of this ravioli and replace it with mushrooms."
Everything is scoped properly and the task is obvious at a glance-- it's just
annoying.

~~~
jmull
> But as you pointed out, there is no cascade and no sheet. The styles
> apparently just apply to the stuff they are near in the code. No twisted
> logic to unwind, hence no spaghetti.

Ah, well, things are not that simple.

In a project of any complexity at all, the style of any individual element is
typically dependent on a number of things which collectively make up the
context of its presentation. E.g, the site theme, the component, and the
individual element (at _least_ \-- usually there's an app-subsection and
components are usually grouped into modules, etc.).

Note that this is inherent to the problem space and is true whether you're
specifying styles in code or styles in cascading style sheets or any other
way.

CSS provides a basic mechanism for dealing with this -- the cascade (though as
I mentioned, IMO it is lacking some necessary features). Styles in code needs
an answer as well.

If you were to simply hard-code styles at the element-level (which you can do
using either mechanism BTW though its probably easier with style-in-code),
you'll have a hard time finding all the places in the code you need to update
if you want to make a change. You'll be doing a lot of full code searches,
reading code, and trying to put yourself into the mind of the person who wrote
the code in the first place.

The "spaghetti" in the metaphor are the lines of dependencies. We have
spaghetti code when those lines are disorganized, entangled with
irrelevancies, obscured, and otherwise unnecessarily difficult to deal with.

In fact, if you hard-code a style on an element that is dependent on the site
theme, app section, component module, and component, you'd be hiding those
dependencies, which creates spaghetti code rather than avoids it.

Now, I expect most developers would naturally try to avoid doing something
like that. I'm just trying to point out why style-in-code doesn't really help
you avoid spaghetti code.

------
therealmarv
In my opinion this is a workaround for a language flaw in the React concept.

Look at this beauty for comparison: [https://vuejs.org/v2/guide/single-file-
components.html](https://vuejs.org/v2/guide/single-file-components.html)

~~~
akuji1993
Hm, I don't share your opinion on this matter, to be honest. You can easily
avoid this in both Angular (which does it out of the box) and React by
including CSS Modules ([https://github.com/css-modules/css-
modules](https://github.com/css-modules/css-modules)) which, if you use
create-react-app to build your projects, is a 5 minute change to your
architecture. So there really is no reason to write that down as a con for
React.

~~~
preommr
I have so many small components that I would loathe to have a separate
stylesheet. Yes, it's a small thing to just switch tabs, but this is a small
problem. And these small problems add up and can be a huge pain. I really
really like the SFCs in vue and compare it to a bit of butter on toast. It
might be a small thing, but it seems like it makes a big difference.

~~~
antihero
So you can just use styled-components as in the OP

------
LeonM
Be very aware that most popular CSS-in-JS libraries (such as JSS) will
completely break CSP (Content Security Policy). The default reaction is
usually "Just allow unsafe-inline in your CSP header", but this is dangerous
advise as it will disable CSP! I've even seen 'experts' advising to use
webpack to set a static value as a CSP nonce during build-time...

If you want to use CSS-in-JS, you'll either have to use server-side rendering
to inject CSP nonces in your index.htm [0], or set up a complex build system
to extract the CSS from your JS so you can serve them as .css files.

Using server-side rendering to inject nonces into your single-page client side
rendered webpage is such an ugly hack. I'd prefer the second solution but I
have not been able to find a solution like that, nor do I have the time to
dive into the webpack rabbit-hole to do so.

[0]
[https://github.com/cssinjs/jss/blob/master/docs/csp.md](https://github.com/cssinjs/jss/blob/master/docs/csp.md)

------
antoineMoPa
The down-side with this is very high coupling between UI logic and style.

If style becomes out of fashion, you have to modify files that contain logic.
If framework (react/vue) becomes out of fashion, keeping styles will be
difficult.

The other down-side is thousands of web developers having to re-learn CSS and
the tooling behind your app instead of just changing CSS files.

~~~
overgard
Ok, but, the average startup web dev stays at a company for like two years?
And then the thing eventually gets rewritten anyway in the latest flavor of
the week, because nobody is using the same tools as two years ago.

I guess the concern for longevity most devs have is amusing when most
software, if its not like systems level stuff, or problems most devs dont want
to solve, tends to get disposed pretty frequently.

By the way, most of the software that actually sticks around was written in C
and generally solves a problem most people wont tackle. Like zlib or sqlite or
nginx or the linux kernel. You can almost pretty much judge the longevity of a
piece of software based on how hard the problem it tackles is. Like encryption
or compression? Those libraries are going to be around forever, because how
many coders do you know that can write a semi compitent encryption library?
And how manu coders can write a templating engine?

Like most of web dev is throwaway code. It just is. Arguments based on like
"will they be able to restyle it in 10 years?" Well are they even going to be
around?

~~~
antoineMoPa
I agree, but it is not really an excuse to write bad code.

~~~
overgard
Absolutely. But im not sure "bad code" is the same thing as code written for a
purpose at a particular time. I think something can be good code if its
lifespan is understood in the context of the business goals. I just get
cynical when I hear people apply these principles to something that may live
five years. Not every project is going to be maintained for 30 years

------
LaserToy
CSS... sweet memories. For some reason I never was able to learn how the damn
thing works. I worked for Google Analitics in 2011 and we rebuilt it using new
in house built framework which championed an idea of a separate styles for an
on screen component. Every dev was starting a new component with: clean_styles
directive as nobody was brave enough to deal with what comes from the top.
Even though it was possible to use cascading part, nobody was brave enough to
own styles for the whole product. So, We ended up with so many styles we had
to split them in couple files as we reached a limit in IE on number of styles
in one file. Last time I checked GA is loading 3 of them... Is it a time for
some other way of doing it?

~~~
LocalPCGuy
> I never was able to learn how the damn thing works

People not taking the time to learn is not a reason to throw an entire
building block of the web out.

(Yes, I realize there are a lot of people who know CSS and still choose CSS-
in-JS, but I'm specifically referencing the point re: not learning CSS.)

~~~
LaserToy
I didn’t say I did not spend time, I said - could not. Same applies for most
people in the team. I think we had coupe folks who were spending a lot of
their time explaining CSS.

My theory is that CSS was something that was treated as a task. Make a lot of
client/server side development and then make these freaking lines align
perfectly. So, most of time engineers were avoiding styles, applying them was
the most tedious and hated part of the job.

And it is hard to be good at something you hate.

~~~
LocalPCGuy
I agree with you re: the task comment, there is a difference between
JavaScript developers and Front End UI developers. It's almost like the full
stack discussion but just in the front end ecosystem.

~~~
tracker1
They significantly overlap, so wouldn't say they are different. I would
suggest that most "JavaScript developers" in the box you'd put them in are
backend developers that only know a minimal amount of JS and don't really know
JS well and by extension the browser itself.

------
benologist
I write CSS in CSS and my JavaScript in JavaScript because at some point
abstractions pile up into this massive cognitive burden for anyone adopting
your code, especially when they didn't follow the exact same path as you
technology-wise or if they're newcomers. I want my work to be pick-up-and-
play, not RTFM x 20 abstractions and tools.

~~~
pitaj
Even if there was more cognitive burden, it's insignificant compared to the
drastically reduced amount of context switches the developer has to deal with.

------
denysonique
While Styled Components, Styled JSX or Linaria (which doesn't require a JS
runtime for production) are nice solutions, the fact that I can no longer use
the colour picker and other tools to live edit CSS from the styles pane in the
Elements tab in Chrome Dev Tools, sometimes makes me want to go back to plain
CSS to get this functionality back.

~~~
jakelazaroff
You can! I do this all the time.

~~~
kowdermeister
With copy and paste? :)

~~~
jakelazaroff
Am I misinterpreting something? In my app that uses CSS-in-JS, if I go to the
"Elements" tab of my browser developer tools and select an element, I have the
option to inspect, add, remove and change styles — including using the color
picker and bézier curve editor — and have it reflected live on the page.

~~~
leerob
When my styled-components app is in prod, the styles are non-editable. When
developing, I can use Chrome Dev Tools. On prod, I have to copy paste. Maybe
I'm doing something wrong?

~~~
exogen
I believe this is a result of it using the "CSSOM" browser APIs for speed in
production. Unfortunately, browsers apparently haven't figured out how to make
such styles editable yet.

It's definitely a limitation of certain CSS-in-JS implementations, but
unfortunately one that inherently comes from "using the platform."

------
antihero
Why is it that whenever anyone posts anything about React, there's a horde of
Vue users trying to convince us that they are doing it better? It feels a bit
desperate.

The great thing about React is it is purely JS (or JSX, which is effectively a
macro for the underlying JS). Which means it is explicit, and predictable.
Perhaps that means there's less sugar, but any sugar and magic comes at a
price.

I'm going to have a look at Vue more anyway, out of curiosity, though.

Edit: I note that some of the anger at React has been "Why does it need
Redux/MobX if it is so good?". But Vue has Vuex to solve the same problem?

------
bpicolo
CSS in JS is one place where Vue has a substantially better experience. Being
able to toss scoped-css, written as normal in a css block is what I call
nailing the developer experience. It is all the best parts of css in js with
none of the downsides.

~~~
cageface
You can do this with styled-components in react too.

[https://www.styled-components.com/](https://www.styled-components.com/)

~~~
preommr
Yea, but this isn't out of the box. This is some 3rd party solution for a
pretty major part of an application.

~~~
apazzolini
I understand your preference for frameworks, but I actually appreciate that
it's not out of the box.

I'd rather have libraries focus on one thing and do it well - the Unix
philosophy. This lets me compose the appropriate libraries for the problem at
hand.

------
cbdumas
I got to web development pretty late (circa 2015) so my perspective may be
skewed but CSS in JS seems much more natural to me than separating markup from
style and then linking them up later with global class names.

It reminds me of when I was in college learning C where all of your code is
just dumped into one namespace, and then later learning Python (or basically
any other modern language) with actual modules and namespaces. After seeing it
done that way it just makes no sense that it would ever be done the old way
again.

------
latronic_notron
In recent projects I tried 3 new approaches: React's CSS-in-JS, Vue's Scoped
CSS and Tachyons/Tailwind Atomic CSS.

All of those solutions were a huge improvement and scaled better than any of
the previous pure-CSS techniques I was using before.

BUT the key here is that those things only work when you rely on React/Vue/etc
components. If you have have to rely on copy/pasting markup, things go wrong
FAST and you lose track of your app style and things get duplicated. You also
to have to enforce SMALL components. If you duplicate markup between
components things get hard (but not as nasty as if you weren't using
components).

I honestly believe that people not using modern frameworks can't see the
advantages of any of those techniques, and would urge everyone to try them out
in component-based project.

~~~
deltron3030
Those techniques work well for design systems. CSS in JS on its own, and Vue's
Scoped CSS are a different thing than Tachyons, Tailwind or Styled System.
Styled System is for CSS in JS what Tachyons is for CSS, you're using a design
system, either the default values that are already present, or your own
customizations.

This basically frees you from making style decisions while coding, depending
on your design system, things will just work well together as you create your
components, with spacing, colors etc. all being already figured out.

This means that you don't "translate" pixel perfect designs, you use design
tools like Sketch or Figma to find the rules and scales that you then
translate into the style sheet/design system.

Instead of doing the "configuration" in your CSS when you're coding, you
basically have an intermediate step where you set up those rules in advance,
and can just focus on composition.

~~~
latronic_notron
> Those techniques work well for design systems.

That's true! I find that enforcing a consistent and quickly-changing design
system is way easier than when I was using old techniques.

> Instead of doing the "configuration" in your CSS when you're coding, you
> basically have an intermediate step where you set up those rules in advance,
> and can just focus on composition itself.

You summed it up perfectly

------
JetSpiegel
Way to defeat the purpose of CSS. How is hard-coding the styles to each
element something better? How can this not lead to MB of worthless crap to
download, instead of the content?

Want to show a title? Use `<h1>`, and style it with `h1
{color:palevioletred;font-size:18px;}`. Except hardcoding the font-size as
pixels is another code smell, the `h1` is already bigger than the text body.
Use `2em` if you really need things to stand out.

It's in the name, Cascading.

------
jpochtar
Thought experiment: imagine doing React development with all inline styles.
Someone invents CSS. Would you use it?

Of course not: CSS is a bad idea in 2019. In 2004 it solved some of the
problems we have React to solve today, but much, much weaker

------
vehemenz
How do you handle advanced CSS Level 3/4 selectors, CSS grid, and media
queries?

~~~
bastawhiz
The idea with CSS-in-JS is that you don't use selectors. Since you are
constructing DOM nodes individually, you don't need to select them. Styled
components can accept props, which lets you style dynamically (e.g., using an
array index to replace `:nth-child`).

With regard to media queries, it depends on the library. For the library the
author is using, the media queries are defined inline: [https://www.styled-
components.com/docs/advanced#media-templa...](https://www.styled-
components.com/docs/advanced#media-templates)

~~~
GordonS
Does it use (shared) variables, like with SASS?

With SASS, I find it really convenient to define variables for common/brand
colours, for example.

~~~
bastawhiz
You can define a "theme" object, which you can inject into your styles (with
an expression inside the template literal). Other libraries support variables
more directly.

------
raphaelrk
I'm always surprised to find no mention of React Native in discussions around
CSS in JavaScript.

They've got it figured out. Stick your styles at the bottom of your component.
Vertical flexbox by default. And... that's about it. It just works beyond that
point.

We liked it so much we ported our webapp from react to react-native-web. It's
an amazing library. You can freely mix in regular react, but the styling story
is so good with react-native-web that you'd never want to. It powers
mobile.twitter.com and the author (same person who made normalize.css)
recently joined Facebook, which hopefully means more development to come.

You'd have to pay me to go back to styling the web with css. It really is a
hair-pulling experience.

------
weslly
What I don't like about css-in-js is how it makes things really hard (or even
impossible) for endusers who may want to use an extension like stylus or
tampermonkey to modify the site styling or behaviour.

------
mxstbr
Author here, happy to respond to any questions. AMA!

~~~
CiPHPerCoder
How do you plan to accommodate NoScript users?

~~~
osrec
I know this will be unpopular, but after a certain point, noscript users just
get a bad experience and that can't be helped. If a developer wants to provide
a rich experience, then there will always be certain platform requirements.
Without them, you will have a lacklustre experience. It's like saying "I want
to have all the whizzy functionality of your app, but I want to access it
using a standard, run of the mill, mud-laden potato" \- it's just not going to
be possible.

~~~
madeofpalk
noscript users certainly signed up for a subpar internet experience, but its
not just them that should be thought about.

Slow internet connections are a reason to think about the experience when
loading JS is slow and/or failed. It's not just 'poor people' who have slow
internet - 'rich people' on inflight wifi or on the internet on the train can
result in things not loading.

~~~
thedaemon
I think this is a big issue with such JavaScript and load heavy web-sites &
apps. They forget that they have users without 1GB connections and who can't
afford, weather financially or location based, the download the 500MBs of data
required to load their web-site. That and hiding CSS inside of JS feels like a
sneaky tactic to keep people from editing it? Or does it actually create the
CSS on the fly? I wasn't quite sure after reading the article.

~~~
ringaroll
No regular JS only website/app required 500mb of data. Please stop
exaggerating. It does not make your point valid.

------
pvorb
I wonder what impact CSS-in-JS has on rendering performance and code size.

I bet that browsers are very efficient at parsing and applying CSS directives
to elements. Parsing and executing the JS and additional DOM manipulations
could have a massive negative impact on performance, at least intuitively.
Does anybody know of a performance benchmark that compares CSS-in-JS to
regular CSS?

------
lousken
If you make sure your site works without javascript as well(unless it's
actually an app) it's fine by me.

~~~
zeroname
This is a requirement that most sites can simply dismiss these days. The
distinction between an app and a website is blurry, a lot of interaction
simply works far better with Javascript.

Supporting "no Javascript" can be costly. It's possible with server-side React
and careful engineering, but why bother? What's the impact on the business?

~~~
lousken
I don't know what the real impact is, but if your site shows me blank page
without javascript(I have it off by default) I am closing the tab.

I don't think supporting noscript version is costly because for me that's how
it supposed to be by default. 90% sites that are currently on the internet
would work just fine without any js and 95% would work with as little as
hackernews has. Modern CSS allows to create most of the experiences and unless
you need some interactive forms or serving live broadcasts, games etc.,
there's just no point in using javascript.

Over the years I've stripped javascript from about 40sites which I visit daily
without sacrificing any real functionality. Those sites download and render
visibly faster, only relevant cotent is shown and I even implemented dark
theme for them. My only javascript fixes are for broken galleries or embedded
videos (and those wouldn't even be necessary if developers wrote a fallback to
noscript).

It used to be that developers loaded many little scripts so I could only block
the useless crap but since everything is minifed and bundled in one huge
unreadable file, I just use uMatrix to block it entirely and Stylus and
Tampermonkey to fix it.

~~~
zeroname
> I don't know what the real impact is, but if your site shows me blank page
> without javascript(I have it off by default) I am closing the tab.

I can show you "this site requires Javascript" instead, but let's just say
you're not part of the target audience and that's fine.

> I don't think supporting noscript version is costly because for me that's
> how it supposed to be by default.

That highly depends on the site, of course.

> 90% sites that are currently on the internet would work just fine without
> any js and 95% would work with as little as hackernews has.

99.9% of websites are not actually businesses that employ developers. If
that's your standard, I agree. A simple webpage does not require Javascript.

------
err4nt
I've been doing almost the opposite - enhancing and extending valid CSS
stylesheets by using JavaScript to define new features and functionality to be
made accessible and usable by writing valid CSS.

An overview of my tooling and workflow is here:
[https://github.com/tomhodgins/caffeinated-style-
sheets](https://github.com/tomhodgins/caffeinated-style-sheets)

The big idea being that CSS should be able to apply to _any_ HTML, no matter
how it was created before it got to the browser. Many style-related tools
integrate tightly into your framework or into one particular workflow but
don't give you the flexibility you need to apply any styles to any website
unless it happened to be put together with specific tools a specific way, but
I don't think that provides enough flexibility.

------
maaaats
I've been using elm-css on a project lately. Pretty cool with typesafe CSS.
Also inline, but since everything is functions it's easy to compose/reuse as
well when needed. (Compared to the string templating shown in this article)

------
designingsean
So reading this article made me have a bit of an epiphany: What is being
described isn't CSS-in-JS. Instead, this is style properties in JS.

This is the equivalent of inline styles. We don't call it "inline CSS" because
it isn't CSS. Nothing cascades with inline styles, just as they don't with
"CSS-in-JS". And you don't have to worry about specificity with either
implementation.

In other words - all the things that make CSS the powerful language it is are
stripped away to just a listing of arbitrary properties.

So, CSS-in-JS, do yourself a favor and stop calling it that, because what you
are coding is nothing even remotely close to CSS.

------
consolenaut
As someone coming from a traditional strict separation-of-content-and-style
background and now convert to Styled Components, CSS-in-JS felt unnatural to
me when I first encountered it. The problems with styles in large applications
are well known and I had a solid handle on them with BEM and other bits of
tooling, namespacing styles to a particular React component to avoid
collisions etc.

It took me helping my brother learn how to do web development to shake me out
of that mindset. He's not from a traditional webdev background and he got
quite far quite fast with React. When he showed me his code, I noticed he was
inlining all of his styles in his relatively small React components. I was
going to explain why its bad practice to do that, but when you're building
small almost atomic components, that approach actually makes a lot of sense,
its what the BEM methodology tries to do albeit in a poorer way. CSS-in-JS
tools like Styled Components preserve the spirit of this approach and minimise
the downsides.

I think CSS-in-JS lends itself quite nicely to atomic design. At my current
company, one of the first things we did was build a component library of atoms
& molecules that are shared across many applications, keeping our design
language very consistent.

We also make heavy use of Styled Components' theming capabilities, so we wrap
our React apps with a ThemeProvider and give it an object with theme variables
that drive the look and feel of our components. This is super useful when you
have to support whitelabeling like we do, but even if you don't, its nice to
keep your mystery-meat colors and spacings all in one place similar to how you
might with SASS.

One of the gripes a lot of people have with CSS-in-JS is portability, and
while that is a drawback, I feel it's an anti-pattern to rely on shared CSS
styles to enforce design consistency across many deployables. It's kind of a
classic case of developers trying to solve a process issue with technology,
which is admirable, but from experience styles go out-of-sync with eachother
quite easily and its rare that you can drop a CSS file into another project
and have styles just work without having to do rework, so the benefits of
sharing CSS rather than writing new styles off a styleguide are marginal at
best. Again, this is all my subjective experience, your mileage may vary.

We still have a couple of issues with Styled Components, no technology is
perfect and SC is still relatively young, but so far the pros have far
outweighed the cons to the point where none of us really feel the itch to go
back to SASS or plain CSS. I'm definitively not a magpie developer by any
stretch, I'm usually resistant to change for the sake of change, but CSS-in-JS
makes a lot of sense when you use it how its intended

------
jasonhansel
I'm of the opinion that CSS actually has more in common with logic-based
programming languages (like Prolog, or more specifically ones based on
defeasible logic) than with ordinary languages of the "imperative" or
"functional" sort. I think that reading CSS with this in mind helps make sense
of some of CSS's features (e.g. specificity, the way selectors work).

------
austincheney
Story of my life as a front end developer... you can invent an abstraction to
make life easier and simultaneously increase code size and complexity more
than 10 fold. Easy is often an anti-thesis of simple.

Basic front end code isn't that challenging, but it does take some actual
practice (not half-ass practice followed by a million poorly considered short-
cuts).

~~~
exogen
What about non-basic front end code?

~~~
austincheney
Well I did spend this weekend trying figure out how to dynamically update
keyframe rules with JavaScript only to discover the window.CSSKeyframesRule
API is incomplete on most browsers so I found a different nonstandard way to
solve that problem cross browser. I have not seen a failure to implement
standards like that in many years.

Just about everything else on the frontend is absolutely solid cross browser
with 5+ years of thoroughly tested support. People don’t write abstractions to
fix weak technology, they do it to fix weak developers.

~~~
exogen
No.

------
cryptos
The problem with orphan CSS is adressed very intuitively in Vue.js with single
file components (HTML + JavaScript + CSS).

[https://vuejs.org/v2/guide/single-file-
components.html](https://vuejs.org/v2/guide/single-file-components.html)

------
brianzelip
Off topic, but I really like the new site design, particularly the Appearances
page!

~~~
mxstbr
I really appreciate you taking the time to comment on that! I put a ton of
work into the design, so you saying that makes me feel really great.

Thank you!

------
pmlnr
> Why I Write CSS in JavaScript

tl;dr because it's convenient.

It's also redundant, goes completely against the features of CSS (the
cascading part), doesn't utilize the possibility of selectors, children, etc,
ugly, and computationally heavy.

But yeah, why not.

~~~
zeveb
Not to mention that it doesn't work without JavaScript enabled on the client
(unless he's generating CSS in server-side JavaScript). That's fine for a true
web app (and web apps _do_ have their place), but it's completely not fine for
a web page, which should display just fine without JavaScript.

People should not be forced to grant you permission to execute code in order
to read text & view images.

------
cleanyourroom
Hi, I'm from the orthodoxy and I'm here to disparage you.

$disparaging_paragraph

Thank you

------
meehow
Every time when some language generator become more popular, it's a sign, that
something is wrong with the main language. It happened to Java, JavaScript,
CSS.

------
hitekker
"Deprecate CSS, disregard design" seems to be the standard practice for
engineers silo'd off from designers, and the business-at-large.

------
8lall0
Nothing in Javascript makes me not afraid, the less i have to touch it, the
better i feel.

SASS + BEM accomplish the result in a more manageable way.

------
graphememes
Why I don't write CSS in JavaScript:

people disable it

------
chiefalchemist
CSS === Cascading Style Sheets

In the context describe in the article, there is nothing cascading, and there
are no sheets.

What he / she is doing is going back to the late 90's and inlining all the
style'ing. I'm not judging the technique, simply pointing out that it's not
actually CSS.

------
headcanon
styled-components is not popular on HN it seems. Allow me to share my own
positive experience:

I have built websites in a variety of different ways, with a variety of
different CSS schemes. I've worked with SASS, LESS, BEM, every major css
framework, in both SPA and SSR environments.

I have also built react SPAs with the above variety of CSS schemes, as well as
CSS-in-JS libraries like Aphrodite and Styled Components.

I currently build and maintain a medium-to-large web app with a small team,
right now ~200 components, 31k lines of js including test files.

Styled Components has been an immensely positive experience for us, and i
would not want to use any other way I have mentioned, or has been mentioned in
this thread, to manage our styles in our app.

The reason why is because of the simple fact that it allows us to think of our
styles just like any other component. We do not need a separate way of
managing styles that we need to keep track of, whether a style is used is 100%
the same as whether a component is used or not, which makes eliminating dead
code, dead styles, easily managed through tooling.

It allows us to define simple, semantically-named components like <FlexGrid/>
and <BigButton/>, and allows us to compose these components together to build
up styles just like any other react component.

Styles are easily overridden from their parents. We use Ant Design for our UI
toolkit, which does not use Styled Components, but any styles we want to
override, as well as styles in nested classes, are easily done by wrapping an
antd component. All the parent component needs to do is accept a "className"
property. This makes interop with other components simple.

Effectively what this means is that after awhile, we get to live in a world
where I can add a component into any given part of application, and be very
certain its going to look and behave the same way it does in every other part
of the application. When I'm building new features I don't want to think about
styles, except when adding styles is part of the feature itself. Styled
Components is the only way so far I've found that does that sufficently.

Globally-available CSS is great for web _pages_ , but not so much for widget-
based GUI web _apps_ , which creates leaky abstractions. Most ways of managing
CSS are systems to get around that, or treat it as a feature.

In short, 10/10 would use again, even over other CSS-in-JS libraries like
Aphrodite. Note this opinion is scoped purely to react apps. Vue's approach
seems appealing as well but I have not used it before, but to be honest I do
prefer being able to have everything in JS or JSX, but thats a different
discussion.

~~~
woah
I hated styled-components when I had to use it. It introduces a ton of
unnecessary nesting and weird abstractions just to give devs something that is
superficially similar to something they are familiar with. I keep it simple
with styles in JS.

------
hypertext7
This stuff irritates me. Imagine if you read an article titled "why I listen
to audio books". Nobody cares. Do whatever works for you.

------
yellowapple
I feel like a lot of this boils down to a variation on Greenspun's Tenth Rule:
"Any JavaScript-centric web development framework contains an ad-hoc,
informally-specified, bug-ridden, slow implementation of half of a web
browser."

 _" I can add, change and delete CSS without any unexpected consequences. My
changes to the styling of a component will not affect anything else. If I
delete a component, I delete its CSS too."_

This is readily achievable with ordinary CSS. Selectors by ID/class have
existed for multiple decades. A Ctrl-F for said ID/class name should be pretty
painless to do even in the case where you're doing everything in one giant
spreadsheet (though in this day and age of CSS preprocessors, no reason why
you couldn't have widget.js and widget.css, the latter of which gets compiled
into the final spreadsheet as part of the build process).

 _" Never go on a hunt for CSS affecting your components ever again."_

I'd hardly call Ctrl-F a "hunt". JavaScript can't fix bad code
hygiene/organization.

 _" I cannot expect all team members, particularly juniors, to have an
encyclopedic understanding of CSS."_

So you expect them to have an encyclopedic understanding of your CSS-in-JS
library instead, then?

Or perhaps it'd me more reasonable to be okay with looking things up every
once in awhile?

 _" With CSS-in-JS, we automatically sidestep common CSS frustrations such as
class name collisions and specificity wars."_

I'm curious how much these are actually problems in the first place (or at
least problems inherent in CSS itself), and how a CSS-in-JS framework expects
to solve them without completely reinventing the browser's styling engine.

 _" This leads to a marginally slower time to interactive, but a much quicker
first meaningful paint!"_

If you didn't try to do everything with a giant blob of JS, you wouldn't have
to do these kinds of ridiculous tricks to reduce time-to-first-paint.

 _" Send only the critical CSS to the user for a rapid first paint."_

If the CSS is not critical, then it shouldn't be sent at all. No reason a
backend framework couldn't selectively send only the CSS relevant to the HTML
being sent.

 _" Simply style your components with a global theme or based on different
states."_

<foo class="widget primary"></foo> <foo class="widget secondary"></foo>

So difficult.

 _" CSS-in-JS combines all these benefits into one handy package and enforces
them."_

Yes, at the cost of needlessly reinventing stylesheets and making it
significantly more difficult to modify the styles downstream (e.g. for
accessibility reasons).

 _" Thousands of companies use CSS-in-JS in production [...] (including this
website)"_

As an experiment, I switched JS off for that page and refreshed. The styling
certainly doesn't seem to be happening client-side. Instead, the HTML source
contains a bunch of obfuscatedly-classed divs and a giant obfuscated
stylesheet in an inline <style> tag.

Surely JS is not specifically needed to achieve this result. This could've
been done with CSS-in-Python or CSS-in-Ruby or CSS-in-C or CSS-in-Lisp or CSS-
in-COBOL or CSS-in-Brainfuck or whatever. It also could've surely been done
with a dedicated language-agnostic CSS preprocessor. Further, it could've been
done the "hard" way (not really hard at all) with CSS selectors alone (since
that is indeed the end result).

------
ringaroll
CSS was a mistake. Adding new features will not fix it. It needs to be scraped
and rethought from scratch. There needs to be a something completely new to
replace it, and it must be a full programming language.

------
martin_a
This sounds like an awful idea.

Just put your CSS in a .css file where it can be cached, delivered by CDNs and
can easily be edited in a single place.

Separation of content and presentation has been around for a good reason. One
should always avoid mixing logic and design because it will break some day, no
matter how well you think you handle it.

~~~
ggregoire
> Just put your CSS in a .css file where it can be cached, delivered by CDNs

.js files are cached and delivered by CDNs too.

> can easily be edited in a single place

If you change the name of a class (or add a new one, delete another one, edit
the structure of the component, etc...), then you have to open and edit 2
files. With author's solution you don't. The CSS is collocated with the
component.

> Separation of content and presentation has been around for a good reason.
> One should always avoid mixing logic and design

Author is talking about putting the React component (presentation) and its CSS
(presentation) in the same file. He's not mixing business logic and design.

~~~
pmlnr
> .js files are cached and delivered by CDNs too.

Not in 2019, in the age of excessive A/B testing, where every page load gives
you a different set of JS.

