I find it very hard to understand what these CSS-in-JS libraries are for, and how anyone can be happy with them. They're all extremely leaky abstractions for what's mostly a 'solved problem' - how do I style something.
What's wrong with just "plain old CSS" with whatsoever pre processor you choose? If you're working in a larger project and what to completely modularise your styles, throw in CSS Modules.
I think this over complicated approach by overloading the style attribute, and then figuring out how to do :hover is just too much snd is partly what others point to and laugh when they talk about "JS Fatigue"
Edit: Look, I love React. We just build a reasonably large site with it using some fairly novel and modern approaches to how to make a website. I have absolutely zero sympathy for this self-imposed JS Fatigue that was all the hotness 3 months ago. But using a convoluted system like Radium is just begging for the JS Fatigue crew to point and laugh at you.
I see this a lot: that people creating CSS-in-JS libraries just don't know CSS well enough to solve their problems. I work with the people who created Radium. They made it because they are extremely experienced CSS developers and do understand what's wrong with plain old CSS.
"Throw in CSS Modules" – that is indeed a decent answer today, and the creators of Radium love CSS Modules. But CSS Modules are what, 10 months old at most? CSS-in-JS concepts and implementations are more mature than that, and get you some further advantages like dynamic, runtime computable styles.
On a bit more of a positive note, I highly encourage people to check out CSS Modules. It introduces name mangling to CSS so you get 'locally' scoped CSS classes which you use by 'importing' them in your view component.
It's 'compatible' with any preprocessor, because it's working on the CSS itself. I think the cool thing about CSS Modules is that it makes BEM obsolete - that naming pattern is now essentially enforce at 'compile-time'.
I was using Radium for a while, but switched to CSS-Modules and never looked back once. Its so much nicer, and you get to keep everything that CSS already has, including a sane readable dom and the ability to inspect elements (not possible with inline-styles when your output is all `style={...huge giant mess...}`). On top of that you still get to use your favorite CSS preprocessor if thats your thing. There's no comparison IMO. CSS Modules fix the scoping issues, and `composes: otherStyle` fixes the rest.
I agree CSS Modules are super neat, but I haven't really figured out a good way to handle cases where the cascade part of CSS is actually useful, like theming.
I like it a lot, but I had a hard time combining local CSS modules with external libraries (such as bootstrap, or a CSS for a plugin) in a previous react project.
I think what's driving the css-in-js libraries is actually a drive for better separation of different concerns (and the close cousin, better combining of the same concerns).
An idiomatic react/redux app will have dumb components which receive data as props, and contain zero business logic; they are solely concerned with presentation. Which is great! Big wins in terms of clarity, conciseness, maintainability, testability, etc.
There's just one exception though: The CSS is still in a separate file, but at least some of it isn't a separate concern at all. I have my custom CustomerTable component which contains all the custom presentation logic for rendering a list of customer based on their current subscription status, and which contains all the JSX for generating the actual DOM, and...none of the styles. But I still need those styles for the component to actually work! It feels weird, once you get used to React, to have 95% of the logic needed for a custom component in one file, and the remaining 5% in another file.
I think a lot of experienced React developers would really like something that was basically "JSX for styles"; some simple syntax that would just make their lives easier and let them create simple, dumb components that contain all the logic and code needed for rendering the components.
That being said, I don't think any of the CSS-in-JS libraries are actually quite ready for primetime, for the reasons you listed. We're currently using CSS modules (as described in detail here[1]), and finding it works really, really well, and just living with the mild annoyance of having tons of FooComponent.js, FooComponent.less pairs.
The hover problem does kind of suck--- as far as I know, Radium (and others https://github.com/FormidableLabs/radium/tree/master/docs/co...) tend to solve it by wrapping components with a component that tracks hover state. And moving the hover-state tracking into React isn't the _worst_ thing--- JS is meant to be in command of the interactive portions of websites, so it does kind of make sense. If your :hover is ever going to have to do more, like show or hide content, it'll have to be in JS anyway.
The "JS Fatigue" haters will be cobolt-maintence programmers of the 2020's, I don't pay much attention to them. Javascript has a lot of churn because we have a difficult platform & language to improve upon.
I agree, it also makes React component much more complex thant it should. I've seen open-source components with dozens of props for the css and where 80% of the javascript code was actually just styling.
I'm not sure what's the gain there versus something like Sass + BEM, except from making the javascript code way more unreadable.
Not to mention the mess in the html if it inlines the css.
Speaking as an outsider the modern sass and less frameworks look ridiculous in their complexity. variables and datastructures, loops and recursion and mixins all break the declarative paradigm.
Not to mention it's all working on top of a complex cascading rule-engine.
Pushing all that programming stuff into regular jsx and inline composible styles looks much more compelling if it's possible.
Doesn't have namespacing and composability is difficult. It's a poor language missing expressivity. Javascript, on the other hand, has all of these. I personally just don't like inlining it because it looks bad in the Dev Tools and you can't simply edit a class and see the changes.
"Plain old CSS" is not plain old CSS: it's plain old CSS plus a pre-processor build step that you then have to integrate into the live functionality of your app.
CSS-in-JS just cuts out a whole swathe of tools and replaces them with what is essentially just JS. Even Radium is extremely limited, because just by inlining styles using pure JS most usecases are already covered.
Sure, but if you're talking about true "plain old CSS" then there are some huge issues that are going to come up in many situations. It's not a particularly comparable solution in terms of power, whereas pre/post processors are comparable with CSS-in-JS.
"Frontend developers don’t usually worry too much about CSS"
"Core developers build some core JavaScript tools/libraries and focus on non-UI stuff. CSS is something they don’t need to worry about."
If you work professionally with frontend code, you damn well better have a deep understanding of CSS. The fact that so many developers who work with browsers don't have this is a major contributing factor to the terrible bloated state of so many modern websites and applications.
I think it's important to make the distinction between "worry about" and "understand". A frontend developer doesn't need to "worry about" CSS because that doesn't impact too much of their decision making about how to build the app. The worry is on the designer, because it's up to them to make a design that fits within the constraints of CSS. But of course the frontend dev needs to understand CSS, or else then they have to worry!
I already know Java, Perl, Python, HTML, enough JavaScript to get things done. Linux server setup, AWS, Rackspace, Relational Databases, enough NoSQL to know its worth leaving until a problem demands it. I also know Git, Django, tons of Django related packages, Eclipse....
I only want to move the button a few pixels to the right. And now I don't know enough tools?
> I only want to move the button a few pixels to the right.
On mobile or on desktop? At what resolution/pixel density? Does this button need to be placed differently when the phone orientation changes? CSS is weird because it tries to solve a lot of problems, not just placing things a few pixels to the right. For that you can use absolute positioning with each element, if you want that level of control, and it's simple.
> I only want to move the button a few pixels to the right. And now I don't know enough tools?
Most of the things you listed are things you wouldn't use as a front end developer.
Is it unusual to expect front end developers to know CSS? I'm not a front end developer but I haven't met a single one who didn't have a good grasp of CSS (new grads excepted).
All these abstractions over CSS seem way to complicated and many way to far from the browser to me.
With Shadow DOM style scoping, CSS custom properties and @apply mixins all coming very soon, most of the problems of composable, reusable styling, and even theming, will have great native solutions.
I'd like to see more focus on reusable polyfills than trying to divert around CSS. Polymer supports all three of those now, but they're pretty tightly integrated so other frameworks can't use them so easily yet.
I've never worked on a team where the front-end developers don't have to worry about CSS. Everywhere I've worked, designs produce assets and redlined mocks, and it's up to front-end devs to figure out how to execute the design. I've never worked with a designer I've known to have an in-depth understanding of CSS. So, from my perspective, embedding CSS in the logic makes a lot of sense.
Sort of tangential, I'm curious about your internal process with this kind of workflow. After you have a new design approved the next milestone is just "here's the app"?
We like to have our junior guys build the "HTML": HTML, LESS/SASS (BEM/SMACSS concepts), JS, Responsive, and cross-browser tested, which we can then review and approve and build the project.
For those of you doing this kind of workflow, building CSS while building components, you just review it all together once the whole thing is done? Which is not a risk as everything is "scoped" or "componentized"?
Another great article! The Kadira team is on fire.
I have been working on a descent sized React.js commerce platform. While I was able to get past writing HTML tags that should be as simple as
<div>Product</div>
using this instead
React.createElement(
'div'
{},
'Product'
);
I could justify this overhead in development time and effort because of React's obvious advantages ( Universal rendering!! ).
However when I started adding in styles using Radium I found myself more frustrated than delighted. There are a lot of situations where writing styles in javascript becomes very inelegant very quickly. While basic CSS is far from perfect, I genuinely felt like I took a step back with Radium and reverted back to the legacy CSS stylesheets I had from our previous iteration.
I do have to note the version of Radium I was using inlined all the styles, I do like the new approach Radium is using a lot better, however I'll likely end up converting my legacy CSS to CSS modules, which has my winning vote for the moment as well.
Thank you for opening up the conversation here. All things considered I'm still not sure if CSS modules are really the holy grail. Curious to see what the future will bring for CSS + JS.
> Frontend developers don’t usually worry too much about CSS. They mostly care about the application’s functionality and the layout of the app.
Whether or not frontend developers do a lot of CSS depends on the skills of the team. Companies prefer to hire candidates with design knowledge and coding knowledge, but a lot of the time those end up being separate roles. I'm a frontend developer and I write a lot of CSS.
What the author calls a "UI Designer", I would call a "UI Developer".
To me, a UI Designer is someone who is mostly concerned with look & feel
and aesthetics, whereas a UI Developer is concerned with behavior and interactions. The former focuses on CSS, colors and graphics whereas the latter focuses on JavaScript. There is obviously overlap but the two roles tend to be very distinct.
* able to have the power of modularized CSS preprocessors for reducing complex styles
* worth the effort.
I'm not against the idea but practically every single instance it comes up it feels like programmers who don't get CSS trying to write something in what they DO understand that handles CSS so they don't have to.
That's fine, and useful, but lets not pretend it's better.
I have - all it shows is that css-in-js is not a realistic competition for sensible modular CSS via something like SASS (CSS Modules, etc, good patterns).
Can you explain your rationale on the first point WRT render time being "waaaay too late"?
If your app is rendered via JS, having the CSS loaded at runtime should not matter: there's no markup to affect (repaint) and the CSS will be available before your React/etc components are rendered up.
only if it's pure browser-side only. Which is fine I guess - at that point you've given up on rendering performance anyhow generally (especially in initial paint).
Well that that point it's slower to paint with CSS-in-JS because the browser won't have the CSS until the very last thing (after asset load, after initial paint, after content load, then after script execution).
Now you could extract the CSS with a build step... but at that point you've admitted the solution is poor (and/or you're not good at CSS) and are just mitigating it by producing real CSS by automation.
That's fine, but it's no replacement for general good practice or domain knowledge.
That's the part I don't get. From the suggested articles explaining CSS Modules I see examples that are easily controlled with simple, vanilla CSS without even the need of a processor. I even see examples where they get more complicated in the SASS part to compare against and yet a simplified CSS pattern (which they even suggest at first) achieves the exact same result. It's almost like those infomercials where the problem is exaggerated to compare against the thing being marketed. I'm interested in these concepts of CSS-in-JS and I really wish the projects wouldn't fall back on such comparisons.
Indeed. CSS-in-JS is solving a problem that doesn't actually exist. Or rather... only exists because many programmers refuse to learn good practice with CSS.
For me, using css classes in a css file has worked fine for reusable components. For isolation, the root element of the component has a class name like class="supermenu". What are the disadvantages of this as opposed to the intricate toolchains being popularized along with React?
Say you have .supermenu .button. What happens if a global .button class enters the picture? The root class is good for preventing leaks but offers no protection.
That's the point that one should start paying attention to what they are introducing into the global scope.
But it depends on the CSS. A global button class will not overwrite the properties of a button class descending from a higher level class. It will only introduce new properties that are not already defined in the button that's inside the parent scope.
There are advantages to having base styles in a global class, but I agree they can get unwieldy if one doesn't have discipline with them.
This is basically what the BEM (block, element, modifier) convention is.
BTW, CSS modules essentially automate and enforce BEM. Each component's CSS file can have a ".button" class that doesn't conflict with any other ".button" on the page because they're automatically name-mangled (https://en.wikipedia.org/wiki/Name_mangling). Then in your React code you do something like
I think we're still in the heavy exploration phase with styles. It reminds me of the explosion of flux frameworks until we finally settled on redux. I'm really hopeful that React will just pick a winner, and the community will stand behind em. In the react-future repo they also have some interesting ideas for taking on layout, which might be an exciting change.
In any case, I think CSS modules are still lacking. I've been using css modules for the last few months, and although I love using em, it still feels like it has a long way to go. With that said, I do think that CSS modules are probably the best general-purpose solution that we have so far (i.e. they work for the largest number of scenarios).
My first problem with css modules was the lack of value types. This is really important for stuff like colors, where you wanna declare a single color value and use it in multiple attributes (background-color, border-color, border-top-color, etc). To tackle that they eventually added module values [0]. Yay! Except that it doesn't work for attributes with commas (i.e. shadows), nor does it perform any kind of validation on the values, so typos are very likely to pass unnoticed. :( And it doesn't play well with other PostCSS plugins.
The second problem is that they don't provide a easy / simple way to tackle stuff like theming or one-off tweaks. I'm not a fan of Polymer, but that's one of the few things that I think they've gotten right. Check out the paper-tabs element [1]. They allow you to pass a css variables (--paper-tabs-selection-bar-color), but in case you don't pass any variable it'll use the fallback (--paper-yellow-a100).
These aren't insurmountable issues, and you can totally work around em, but I'd hardly consider em ideal.
I'll note one thing that I absolute LOVE about css modules and css module values: dependencies are explicit! You import specific values from different files, so it's very easy to see from what file each value come from. It's the same thing with composed classes. This is actually one of my bigger issues with Polymer: HTML imports just pollute your environment with all their junk. You import a file without any clue of what just got pulled in! If you're looking at a file with a handful of imports, good luck tracing where everything came from. It makes reading Polymer code very unpleasant. On top of that, Polymer decided to go with mixins as their composition strategy, which is also difficult to trace... Even after the React community tried em out something similar and eventually decided to move towards using higher order components.
Going beyond that, our style strategies are all really hard to share with others. If you want people to be able to use your components, you end up falling back to global css.
React Native's Stylesheet class seems to be one of the better options for inline styles (or more specifically, React Native Web's version). However, it's only good for app styles. If you have a website, it's probably not a good choice: it doesn't have any way to reset browser styles, nor does it allow you to target plain elements. I had wanted to use React Native Web's Stylesheet class for a website that was using React without any client-side JS (only server-side rendering), but once I realized I'd have to pull in even more tools to style other stuff, I dropped that idea.
I'll also note that React Native Web's Stylesheet class can be problematic in certain apps. For example, if you receive pre-compiled HTML fragments from the server and your only way of targeting those elements is to use nested selectors. Normally you'd have styles that look like this: .FooBar nav h1, .FooBar nav h2, etc. But that's not doable at the moment.
Hopefully this doesn't come off as a negative rant, because I'm actually REALLY excited to see so much experimenting and progress being made in this area. I have nothing but the utmost respect for all the awesome developers that are trying out ideas left and right.
What's wrong with just "plain old CSS" with whatsoever pre processor you choose? If you're working in a larger project and what to completely modularise your styles, throw in CSS Modules.
I think this over complicated approach by overloading the style attribute, and then figuring out how to do :hover is just too much snd is partly what others point to and laugh when they talk about "JS Fatigue"
Edit: Look, I love React. We just build a reasonably large site with it using some fairly novel and modern approaches to how to make a website. I have absolutely zero sympathy for this self-imposed JS Fatigue that was all the hotness 3 months ago. But using a convoluted system like Radium is just begging for the JS Fatigue crew to point and laugh at you.