Hacker News new | past | comments | ask | show | jobs | submit login

Why the hell are we now putting CSS in Javascript? I'm losing my mind with web developers trying to control everything in the world with client-side javascript.

What a mess.




Styling with JS is simply a much better experience than using stylesheets.

Like it or not, styling often changes in accordance to changes in the application state. Instead of reacting to state changes by appending/removing class names, you can remove much of the friction by making style a part of the application state and changing style directly when the appropriate state changes.

By using inline styles exclusively, styles are now completely local and isolated by default, and can never have any unpredictable cascading effects throughout the rest of your app. We simply cannot understate the importance of this guarantee of isolation in a component-oriented architecture.

We also gain all the facilities we might possibly need to programmatically manipulate our styles since they're now just JS objects, without having to resort to the clunky DSLs offered by preprocessors like LESS and SASS.

Last but not least, we can enable far more granular style reuse using plain JS objects by leveraging the excellent built-in ES6 module system, and automatically benefit from module optimization techniques in advanced module loaders like Webpack to remove unused styles in production.


Only real downside of inline styles is that they're a subset of real css, and are not as expressive. Goodbye using pseudo classes like :focus, :active, etc with just the React 'style' object. And for things like designing input components, they're really important. You could hack around this by maintaining component state (e.g., flipping a boolean for mouseEnter and mouseLeave to emulate :hover), and use the boolean within your styling logic, but that is pretty hacky.


That said, with react tools like https://github.com/threepointone/glamor or https://github.com/milesj/aesthetic * you can get the best of both worlds. Isolated css plus :hover and other psuedo attributes.

* or https://github.com/dowjones/react-inline-style or https://github.com/martinandert/react-inline ... there's a lot of options


Note: The library rebass uses, styled-components, doesn't use inline styles. It takes your styling and injects it as an actual style.sheet with automatically generated class names! This means you have the full power of CSS at your fingertips without having to resort to component state for e.g. hover.

See this article for more information about the difference: mxstbr.blog/2016/11/inline-styles-vs-css-in-js/


Nice explanation. I agree. Removing the cascading effects is an especially big one.


> are we now putting CSS in Javascript?

You are missing the point. Forget about client vs server, the idea is that in React you are working with components.

NOT putting component-local styles into the component's implementation is a mistake, and is equivalent to creating a cluttered global namespace with lots of stuff you shouldn't touch because the component expects it to work a certain way.

The right way is to let each component accept style props that the consumer is supposed to be able to change, but to keep the rest of the component's implementation private.

The idea of encapsulation is pretty basic in software engineering (functional and OOP) but for some reason people fail to realize that what makes components useful is that they create an encapsulation boundary that should reduce the cognitive load of using the component.


While I don't necessarily disagree with the benefits of encapsulation - not even native Android applications behave this way. What are your thoughts on that system, and is this simply because CSS is unreliable, or is your stance that this should always be the case?

What happens when I want to change every button from green to red? Does that happen in one place, or now many?


> What happens when I want to change every button from green to red

If you have a component that you maintain, it can depend on a global style definition that is itself a module. You can change the color of the button in that module.

If you have a component that you do not maintain, then you may look at the implementation of that component and change something that is currently "blue" to "red", but how do you know for sure that the maintainer of the component may not have something in mind or may choose to refactor that code or change the naming convention?

> is this simply because CSS is unreliable, or is your stance that this should always be the case?

My view applies to any approach to code that benefits from a distinction being drawn between a public and private interface. Generally, these are scenarios where the person or team maintaining the component may be different from the person or team using the component as a part of other code. The public interface is meant to be stable and behaves like a contract between the author of the code and the person using it. Semantic versioning is about declaring that public interfaces are or are not stable from the previous version.

If we put our styling code (usual data literals of some sort) into the global scope, but we plan to use conventions established by a component's author as our own convention, we risk the chance that the component's author may change something that we are depending on. The logical separation of styling code that is an implementation detail is what is important, not where in the codebase the declarations reside.

If a component author determines that the user of that component should be able to change style attributes a,b,c,d, and e, then those should be explicitly handled as part of the public API and the values passed to them (and whether they are required for proper functioning of the component) should be defined as well.

This is just good component hygeine. It helps insulate the consumer (person using the component in her own code) from having to read the component's source code to see how the implementation works simply to add styling information.


This is what Shadow DOM and CSS Custom Properties are for: Let the browser encapsulate styles, with both upper and lower bounds, and let specific values inherit through the encapsulation boundary.


Yes. These concepts are gradually starting to take hold in the web and traditional DOM world as well. Oh what a wonderful world it will be!


Don't knock it 'til you've tried it.

I thought progressive enhancement was gospel until app complexity exploded. I thought JSX was an abomination. I was wrong.

CSS Grid is better than table-based and float-based layout. JSX is better than templates. A lot of our old school ideas have either been proven wrong or evolved.

Is styled-components better? I don't know yet, but so far I like it.


> Is styled-components better? I don't know yet, but so far I like it.

Consider these two scenarios:

a) Someone using your component must also understand your component's full stylesheet and must determine (through analysis or through your naming conventions) what she can safely change about your component's styling, vs which parts are likely to be changed by you (or completely refactored) in future versions.

b) Someone using your component gets an API for the things they should be able to change about your component. The rest of your component can be updated (and its implementation changed) as you see fit, and as long as the consumer has followed your public API, the new version will work.

I think that with scenario A you lose most of the benefit of components, since you expose (and force the user to understand) some of the implementation details that she should not modify.

Whereas with scenario B you get the benefit of having an encapsulated unit of code with a clear interface, while being free to modify its implementation as long as the public interface continues to work as expected.


An additional bad part of A, if you look at many bootstrap sites, themes and components that aren't built from source projects, is you also wind up with a LOT of bloat for style definitions that aren't even used. Winding up with kludge on top of kludge, in a large project, where eventually you have to deeply namespace everything to overcome some abstract rule for a part of the app/site you can't even find if it's used anymore.


There's tooling for that: https://github.com/simlrh/dead-css-loader

CSS modules are about 95% of the way to making this a solved problem.

Obviously this relies on imported components implementing CSS modules, but for a greenfield project this kind of thing works remarkably well.


Have you ever built an SPA with globally defined stylesheets? It's a huge pain that's near impossible to maintain. I still have nightmares from that time I tried to migrate a backbone application from Bootstrap 1 to 2.

It's not about CSS in JS, it's about having locally scoped CSS. Using JS to do it is just one approach.


Yes - more than one. The complexity is also a function of team size. I ran an SPA by myself for an entire organization and didn't have a single problem writing raw CSS.


Sure, everything is easy when it's just you. The value of having abstracted, localized CSS on a long-lived team with multiple developers cannot be understated.


Why not?

Don't get me wrong, I had the same reaction as well when I first saw it, but the HTML/CSS/JS divide only really makes sense when you're making a traditional HTML document. When we're making component-ised UI elements, separating out that code across HTML templates, a JS file and a CSS file doesn't actually make that much sense.

I don't personally use JS-ed CSS like this, but I also don't think it's a totally insane idea.


Imagine the case where button color is embedded into the implementation of every component. If a UX designer decided that the new apps' brand will be partly new button colors - congrats, you'll have to change every button component instead of a single line of CSS.

Fully encapsulating components is one thing, especially if their encapsulated implementations use shared stylings under the hood. Anything else is repetitive copy-pasta that will be difficult to maintain.


> Imagine the case where button color is embedded into the implementation of every component. If a UX designer decided that the new apps' brand will be partly new button colors - congrats, you'll have to change every button component instead of a single line of CSS.

Not at all. In fact I'd argue it's just as simple if not even simpler than having plain old CSS in that use case. You could easily have brand colours in either a theme or config file and there you go: one line of change. As others have said it's a lot easier than it sounds and styled-compenents makes a lot of sense especially in a world where a lot of places are preprocessing their stylesheets with SASS or LESS.


I don't get it, why do you have so many button components? If you have different buttons for a number of valid scenarios, it follows that each scenario should be reconsidered during such a rebranding.

The problem you're describing shouldn't actually exist in a well-structured component system based on a well-considered design system.

Secondly, nothing is stopping you importing constants representing brand colours, spacing and typography from other modules, then using them in your component styles. In fact, this is what people actually do.


No, that's the OPPOSITE of what happens.

With styled-components you define the theme once, and then just use those variables in all of your components.

With plain CSS you end up sometimes repeating the same value as a color or a background-color or a fill or stroke and then you need it to generate a dynamic value in JS and suddenly you either have to come up with clever tricks involving semi-transparent overlays or you copy the same value from your CSS into your JS and now everything's horrible.

Styled-components and "CSS in JS" solve that. Sure, CSS variables solve that too (except when you need the variables in JS), but out here in the real world people have to support browsers that don't support CSS variables.


Here's a good explanation of 'why CSS-in-JS': https://medium.com/seek-blog/a-unified-styling-language-d0c2...


Rendering CSS from javascript is not new nor unique and in my opinion not "a mess". Hell, rendering domain-specific declarative languages in programming languages is not new or unique.

This tool isn't even "putting CSS in javascript", it's putting CSS interfaces as first class interfaces on JSX.


Au contraire, global stylesheets are a mess. Good riddance.


Their very structure is one which is namespaced, there is no other way to format a stylesheet. Sort of like "Global code" oh woe is me, I put my new class in a namespace but it's still accessible from everywhere and can be shared to other places.


You know what's better than namespaces?

Encapsulation.

Why bother coming up with namespaces in CSS in addition to the structure of your JS if your components need both if you can simply let your tooling generate the namespaces for you?

And god help you if you ever need to resolve naming conflicts when using third-party CSS. With "CSS-in-JS" you get that for free as part of the conflict resolution of your module loader.


CSS is a stopgap until the next styling technology comes along. The idea/implementation is correct but the technology is not.

CSS is old tech based on old ideas. It still has its place but needs to be superseded.


If CSS is a stopgap, then HTML is a stopgap. What other technology for styling HTML and browser web pages do you think should exist? What do you think should replace it?

Keep in mind that even Rebass uses CSS to style.


Well, HTML is a stopgap, just as CSS and JS are.

The idea that we're trying to build medium-scale application UIs using a tool set intended to mark up documents with modest formatting requirements is still as crazy as it always was. Pragmatically, we can do it and make stuff work, and because of the compelling advantages of browser ubiquity and the distributed nature of the Web, we put up with the shortcomings, at least for now.

However, none of HTML, CSS or JS is actually very good for full application development. We had better technologies for native applications decades ago. If mainstream operating systems had solved their application deployment, maintenance and security problems within the same time frame, web apps would probably never have existed, and developing modern front-end code for distributed software would probably be much, much easier.


So... let's write everything in Javascript.

Got it.


Not sure what you're getting at. I'm literally suggesting the exact opposite would be preferable.


HTML is holding up pretty okay at it's stated mission. We're able to learn to avoid the shit parts, and we're able to build abstractions on top of it. CSS is failing at it's stated mission, which is to separate style from markup. Only the simplest toy apps can separate style concerns in practice. The whole thing is shit, there's no good part, and there's no way to compose it or build abstractions, except to just do it in javascript.


I think Arkham Asylum has a wing for non CSS-in-JS nutcases ;)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: