Hacker News new | past | comments | ask | show | jobs | submit login
CSS in JavaScript is like replacing a broken screwdriver with your favorite hammer (zendev.com)
175 points by kbal11 on Sept 11, 2017 | hide | past | favorite | 137 comments



The argument here is that CSS should be kept seperate because it is just the design and doesn't affect the behaviour. But this really isn't true. Want to create dropdown menus or tabcontrols? HTML just isnt enough, you need a whole set of styles in order to even create these controls. Additionally why am I able to do animation in CSS? Or insert new HTML elements?? This thing has grown far beyond simple colour switching and changing font sizes.

In fact the seperation causes so much mental overhead, that we need interactive browser dev tools just to be able to find what styles are applied to what element. So ultimately the idea of putting everything in one spot, per component, is actually pretty reasonable.


Agreed. To take the author's metaphor a step further:

the reason the screwdriver was broken is because we're trying to use it as a hammer. So replacing it with an actual hammer makes sense. And the thing is, we still have a fully functional screwdriver at our disposal (for global styles, e.g.).


The metaphor is fundamentally broken anyhow. Hammers and screwdrivers are the same class of things. CSS and JS are not. One is a non-Turing-complete [1] language for declaring properties based on matching criteria. The other is a full programming language. Since metaphors are worse than useless when you already understand the thing, and I think we all understand the things in question, I won't find a better one. I'll just point out the original one is useless.

I've considered JS taking over CSS more and more thoroughly inevitable for about four years now. The pressures on CSS are just too intense for non-Turing completeness to be anything but a leftover remnant of the dream of the "Semantic" web, doomed to fade the same way [2]. People want what only hooking a programming language up to the layout engine is going to give them. You can see it in CSS itself, as it grows ever more "declarative" styles that involve introspecting into the elements themselves, at their content, at their position in the tree, at their siblings.... CSS has long since let the camel into the tent.

(In fact per my earlier comment today, https://news.ycombinator.com/item?id=15218359 , I would consider even CSS-in-JS to still be an intermediate phase to where we're truly going.)

As for the fact that it will be a mess... well... yeah, it will. Welcome to the web.

[1]: I know about the "Turing complete" CSS. It requires user interaction. Cute, but nothing more.

[2]: "What? The semantic web is stronger than ever! Just look at what Google does with its search results!" ... which is a mix of some ad-hoc tags that are rarely the RDF tags the Semantic Web vision was based on, and a whole whackload of machine learning and language analysis. The Semantic Web vision was fundamentally that we can just hand tags out and everybody in the world will eagerly and accurately classify their stuff for you. It has failed (for reasons meditating on the previous sentence will make abundantly obvious), and what today seems to be the "Semantic web" is even moreso a repudiation of the original ideas, rather than confirmation.


"RDF" != "Semantic Web". It's certainly one vision but it's not the vision. And the Google example is relevant because the primary reason it became so useful was that the semantics of the anchor tag lent themselves well PageRank, which was useful well before they had a "whackload of machine learning and language analysis" in play.

It's probably fair to say the semantic web is about trying to make your data accessible. It includes considering that you don't know what the user agent is going to be, what degree of separation there is between that user agent and the user, how the people behind it might find whatever data you're presenting to be useful, what the capabilities of the user themselves is. So you make some effort to produce a resource that's legible to person or machine guided with reasonable direction. If you know there's an existing convention for expressing semantics that overlap with your domain, sure, use that, but if not, any thoughtful reflection of the underlying data will probably be useful.

This does take some effort, and there's the question of whether or not it's worth it, particularly in a business context, because the unexpected uses of your data are often opportunities for others to not only add value but capture it. The Google example is relevant here.

But the other thing is, in my experience, it's useful to you. There's a dictum attributed to Torvalds: "Bad programmers worry about the code. Good programmers worry about data structures and their relationships." I've observed that when a web application project is oriented around thinking about relevant data and its semantically-accessible representation (that "R" in URL), the overall legibility of the project improves from an engineering perspective.

Right now, with the approach of treating the browser as The VM That Lived™, it seems to me the gestalt is very much about worrying about the code.

None of this is to say, though, that CSS is THE way to style documents. There's nothing about semantic resource oriented thinking that precludes using JavaScript or something else to control visual presentation. There's a lot of ways to use JS to do things worse than CSS, and CSS despite some serious warts does have a couple of decades of good thinking put into it as well, but I think there's a case to be made for examining approaches from JavaScript or another DSL (or DSSSL, heh).


"And the Google example is relevant because the primary reason it became so useful was that the semantics of the anchor tag lent themselves well PageRank, which was useful well before they had a "whackload of machine learning and language analysis" in play."

I'm talking about how Google now knows business hours and addresses and other such things about local businesses. It isn't because local businesses went in and labeled their HTML semantically. I was interacting with one business a couple of months ago that literally left the stock photos of restaurants up on their webpage that look nothing like their current location, and didn't care, because as far as the business owner was concerned, if the menu was up, the website was basically done.

"It's probably fair to say the semantic web is about trying to make your data accessible."

I'm not just using the Semantic Web in a vague way. I'm using it in the way in which the term was used ~2005 (and a few years in each direction), when the religiousity around declarative CSS and such was at its fever pitch. It was not just a vague desire that somebody find something useful; people literally thought someday you'd be able to do things like

     import semantic
     print semantic.Website("http://www.chilis.com/").Get("CEO")
and that the "semantic" would not require what it does today, which is "a whackload of ML and online services", but would all work with glorious web standards.

It failed. It failed hard. It failed so hard and so big that there's still people who haven't processed its failure, because they still think something like "it hasn't been tried", without realizing that that's how hard it failed... it was such a failure that it wasn't even a thing that could be tried because it was too impractical. But every once in a while the idea still pops up like a shambling zombie that doesn't realize it's been made dead twice over.

CSS itself isn't vestigial, but a lot of aspects of its design are, including a lot of people's vague hopes about how maybe someday it'll sort of kinda become "Semantic" someday if we just keep hoping hard enough, despite its decade+ record of failure on that front. If somehow the web had been nothing but style tags until today, and we set out to replace CSS, I seriously doubt the result would be CSS again; it would probably be a JS extension.


> I'm talking about how Google now knows business hours and addresses and other such things about local businesses. It isn't because local businesses went in and labeled their HTML semantically.

Consider, though, that this is in part because there already are conventions for this kind of data that make it easier for people (or machines) to pull that data out of the page. The semantic signifiers aren't markup, which moves the problem out of the trivial realm, but they're notable enough it's not even particularly necessary to use machine learning to find them.

Addresses and hours are actually examples of the utility of semantic conventions, even if they're not part of a markup spec.

> I'm not just using the Semantic Web in a vague way. I'm using it in the way in which the term was used ~2005 (and a few years in each direction), when the religiousity around declarative CSS and such was at its fever pitch.

Speaking of religiousity, the religious world has fundamentalists who see their texts claim a flood covered the whole earth and believe the only way to read that is absolutely and literally. There are atheists who agree that's the correct way to read those texts and so obviously they're ridiculous and consequently without value. It's interesting how often the anti-religious and the fundamentalists agree on premises if not conclusions.

There was a movement of true believers in a specific vision of the semantic web. What you're talking about may be the only thing those people mean by the semantic web, but it isn't the only thing that people have meant when invoking concerns about semantic markup.

Perhaps it is silly to get bogged down in a discussion of the semantics of the phrases like "The Semantic Web." Perhaps instead it would be helpful if we could introduce some distinctions through the increased structure of formal terminology?


> I've considered JS taking over CSS more and more thoroughly inevitable for about four years now.

If you spent four years trying to write UIs on the order of 100k SLOC and style them without CSS, you'd realize pretty damn fast that you want CSS.


It's more like a screwdriver with a fancy attachment that makes the screwdriver look cool but harder to use.


By far the most elegant solution I've found for this is TypeStyle [0]. Composable typed JS objects-as-CSS are a revelation and lend themselves to the kind of abstraction/extraction that most devs do everyday.

In contrast, inline parsed CSS such as styled-components seems nuts to me.

[0] https://typestyle.github.io


I’ve very glad you posted this. After trying and hating styled-components, this seems like exactly the solution I was looking for.


What do you hate about styled-components?


Not the op, but the big thing is that the styles are just strings instead of a JS object so you lose a lot of the modularity and composability benefits of writing it "in" JavaScript.

The syntax was also awkward to me at first:

  const StyledLink = styled(Link)`
    color: palevioletred;
    font-weight: bold;
  `;
I thought in JS you couldn't invoke a function without the parenthesis, but apparently you can if you interpolate the string with backticks first? I've done a lot of JS development and I've never seen that before, so while it's nice that it's cleaner it just got in my way of understanding what's going on. I'd rather just do:

  const StyledLink = styled(Link)({
    color: "palevioltred", 
    fontWeight: "bold" 
  })
It looks basically the same but is immediately intuitive and much more powerful since the styles are objects instead of a string.

(Edited for some formatting)


Styled components uses tagged template literals so they aren't just strings and are very flexible. This blog post is a great explanation http://mxstbr.blog/2016/11/styled-components-magic-explained.... For example

const Button = styled.button` font-weight: {props => props.active ? 'bold' : 'none'} `; <Button active > This will be bold </Button>

I've found it to be very handy.


Interesting. Totally possible that I just never learned the power of tagged template literals, I only tried styled-components for a couple weeks.


Can this be used in a react component's <style jsx>? That would seem to eliminate the "copy paste" problem the author of the OP mentions, as well as allow for great DRY practice. JSX + TypeStyle sounds like a really maintainable, reusable solution.


Thank you, this seems excellent.


The problem that you have described (relation between pieces of HTML, JS and CSS code) is solved by using components/widgets (for example: using BEM).

I think the problem is that developers do not understand that CSS should be treated like other languages, and developers should organize it rather than let anyone write it as they wish. You don't write your server code in a single file without functions, using global variables and introducing side effects, you don't let a trainee edit important code without reviews, why do you do it with CSS?

I remember reading that Github had something around 9000 CSS rules on a single page. Github developers are talented, but somehow they didn't pay proper attention to CSS code too.

CSS code should be split into components, should be easy to analyze, and should be written so that minor edit of one widget won't break something else on another page.

> In fact the seperation causes so much mental overhead, that we need interactive browser dev tools just to be able to find what styles are applied to what element.

That means CSS is not well organized.


Agreed most problems can be solved by CSS only. My argument would not be we're solving something in CSS, we're simply removing the friction by having the HTML and CSS separate.

I was one of the skeptics and felt CSS, SASS, or Less.js was good enough for me until one I day I was tired of setting up my loader in Webpack and I just dropped in styled-components.

And then my JSX was more beautiful because my tags now had its purpose in the name. And I didn't need to worry about class names anymore. And adding variations (modifiers in BEM) was a breeze. And I didn't need to go back a forth between the CSS and the component to style it. It was just so much better that now I'm a convert. I still can work with CSS only but the convenience that styled-components brings to my components is invaluable.

I hope this sheds some light as to why we prefer to write CSS in JS than writing good old CSS.


"it's because you don't know the tool and don't use it properly" it is likely more a problem of CSS ergonomics more than a global developer and designer population problem, don't you think? We don't have heated debates at this level around SQL, HTML for instance. Granted, people complain about JS a lot as well.


I really disagree with your take on this for a simple obvious reason: disabling scripts means the page does not work anymore while disabling css means the page looks plain and basic but it retains functionality.


If you do server side rendering, and you have to if you want your page to display with no script on, you can safely put your style in your JS with most of the techs around and have proper display.


THIS! CSS-in-JS just makes so much sense to me and it's a joy to use. Especially solutions such as Glamourous and Styled Components. I have a hard time relating to people who don't see its obvious advantages.


Just to add on here, I think you are exactly right. The author is pretty vague and doesn't provide any concrete examples. I always think, whenever working with JS/CSS/HTML to build a UI is just like any other UI system in terms of separating concerns and good programming practices.

If the browser is what I have to work with then I am going to be writing JavaScript to manipulate HTML / CSS. No amount of CSS wizardy is going to really help. At the end of the day my logic is in JSS and I have to update a UI somehow. This is where and why design patterns like MVC are so popular. You can do all the ugly integrated JS/HTML/CSS in UI components just like in any native UI toolkit and then you update these thru your more pure "controller" logic that tries its best to just shove some data at the UI later and let it do its thing.

Somewhere, if not MVC, but still with some separation between UI and your app logic you still have code that says "Okay, some state has changed, anyone that cares, here is the state that has changed."

I think what the author laments is that is is extremely easy/tempting and common to just dig into those always available globals to solve design problems. This is why so many JS template and other frameworks exist, everyone is trying to find a nice way to do this that makes sense to them. So, I don't care what you do in your UI layer. If you want to make a rats nest of CSS in JS, go for it. If you want to create some beautiful HTML+CSS+JS design that minimizes JS and CSS weirdness, go for it. As long as you give me an API to deal with your thing and not some ass-ugly encapsulation breaking thing that makes me deal with the UI I can separate out the coding effort into better conceptual parts.

This is where people get frustrated with modern JS. As an experienced programmer I can often get things done quickly in most environments and figure out the key parts pretty quickly, even when you are doing things like dependency injection or I have to go through your abstracted bi-bidirectionally dependent class hierarchy hell, I am okay with this. Drop me into a modern JS stack where in order to "do things right" I have to basically completely relearn CSS and figure out a dozen new esoteric and new JS micro frameworks and I just get annoyed.

So far the only antidote I have found to this was Vue. It seems to support this more immediate dirty style of scribbling with DOM globals or the fancier modern things advanced JS/CSS UI folks know how to do that take days of `npm install` and packing and minifying and JSXing and whatever the heck else is going on in the JS world these days.

Anyway, my point was, deal with it. CSS/HTML/DOM kind of suck as a UI layer, but they work. Hide it in your basement. Don't let it infect the rest of your code using well tread design and programming practices. Get on with your life.

edit: Just to add, my one real criticism for the topic of discussion here is that it takes a LOT of esoteric, bleeding edge knowledge to "do the right thing" in JS/CSS these days. CSS is always adding new things and it creates a compatibility nightmare. As a casual occasional person that wants to write a UI using CSS/DOM I am never going to a.) reach the complexity where this matters and b.) have time to learn all that stuff to do it right. I am not convinced big teams with people dedicated to this chore can learn quick enough to keep up while still building a system that plays well with development teams and their speed of knowledge consumption/learning while trying to ship code. Old school things still work, are reliably, and solve the problem 80-90% of the time.


I mean, HTML5/CSS3 has literally been shown to be Turing-complete. I think it's beyond the realm of "just styles"


I think Vue's single-file component approach is a good solution here, allowing you to keep all three separate but in the same file with the additional option to keep the CSS scoped and add a preprocessor to it.

https://vuejs.org/v2/guide/single-file-components.html

About CSS in JS, though, it mostly just seems like a different way of getting the same thing on the page, changed only by the idea of scoping it to some component and maybe some needed flexibility when building dynamic CSS rules. I'm still not convinced any of those CSS approaches propped by the author are necessary or even necessarily that helpful. They can be confusing to developers not familiar with it and burdensome when truly not needed. I'm open to other opinions, though.


I am really digging Vuejs and its single file components. The <style scoped> part makes it even better for me. No more searching through codebase for where the css came from vs. where the JS is coming from.


Just going to chime in with 'CSS Modules' - this approach of scoped-css generalised to use with whatever framework (but most commonly, React)


I'm going to nth this! I really enjoy Vue's way of managing these separate but together.


Agreed. I really enjoy the way Vue handles this.


I too am often confused by things I'm not familiar with, but I don't blame the things for that. Although I reserve the right to blame them for other things once I am familiar with them.


Snark aside, I meant as it relates to developers new to a project, it certainly increases ramp-up time and overall cognitive load, to use the author's words.


I completely agree, I put global styles in my front most component and scoped ones in smaller very specific ones. It's been a really great change for my workflow.


Fully agree, VueJS is great! I always asked myself why someone would need different styles in just one component and not globally:

* Is there any special usecase for that kind of feature? I mean a button is a button and should always look the same (except maybe size and color)...

* Aren't components always looking the same way and a simple naming/clustering-strategy like BEM is enough to be flexible to change the style of some specific component?

[Edit] formatting


C++ added scoped variables and it was generally regarded as a good thing. Is a 'naming strategy' a reason not to have scoped variables in regular programming languages?

Scoped CSS (like CSS Modules, or whatever Vue has) is just taking BEM, building that into the language and handling it for you automatically without having to worry about silly Block__object--modifier rules.


There are few applications like lets say the component renders a D3 graph and all you need is style contained only to that but I tend to always place my styles globally than keeping it in each Vue file.


I agree.

I'd like to add that IMO the right approach is to use CSS that belongs to a component in the .vue file, but also keep a global CSS project for utility classes.


I don't think this guy gets it.

In real life large web apps CSS is very coupled to behaviour and DOM structure. A large part of the advances towards _adaptable_ component-based code comes only when you let go of principles like DRY.

Let me put it this way, if I come along to change a feature in one of the 100s or 1000s of components in a project I _only_ want to think about the JS and CSS in that component's folder. I don't want to think about how that component exists in a vast web of generic CSS utilities and abstracted decoupled code. Copy and pasting CSS properties is cheap. Conversely overly abstracting your presentational code is a short cut to expensive CSS spaghetti.

It's about component encapsulation, which intimately includes its visual presentation. If you can't think of your component as encapsulated single unit then you might as well not be using components. And if you're not using components, then for the love of God don't use CSS in JS.


> A large part of the advances towards _adaptable_ component-based code comes only when you let go of principles like DRY.

> I don't want to think about how that component exists in a vast web of generic CSS utilities and abstracted decoupled code. Copy and pasting CSS properties is cheap. Conversely overly abstracting your presentational code is a short cut to expensive CSS spaghetti.

You probably know this, but based on your phrasing I just wanted to point out that DRY isn't for mechanically compressing source code; it's for removing 'out of sync' issues, like causing bugs when we forget to update this copy of a procedure when we altered that copy.

Removing such 'conceptual repetition' makes life easier, since (a) we don't need to remember any couplings that need to be kept in sync (this is the "obvious" benefit), but equally importantly (b) if there are multiple copies of something, we don't have to worry about the other ones since they're not related.

It's perfectly fine if many similar chunks of code are scattered around a project, as long as they don't have to be 'kept in sync'. The whole point of "components" (/modules/packages/etc.) is to be self-contained, so it's perfectly reasonable to avoid coupling them together in a "vast web".

    Wrong abstraction < Redundancy < Elegant abstraction


You're right. I think we're on the same page. I was trying to get across the idea that CSS and visual presentation is a special case, peculiarly unsuited to DRY. Often visual features are only superficially similar ... e.g. at a certain stage in development the "Foo" component is superficially visually similar to the "Bar" component. If we then couple them together by both using the same CSS, but the implementation diverges as new features are added then we've given ourself a headache.


In CSS if several components have similar styles it is often better to copy-paste because in future you might need to change those components independently.


> Copy and pasting CSS properties is cheap

Why even bring that up? All 'CSS-in-JS' approaches have a way to reuse styles without having to resort of copy and paste.


That's what got me with it - the author states as if it's fact that best practice for CSS-in-JS is copy and paste, but I've never seen anyone advocate for that. Especially with Webpack etc, it's trivial to just import JS styles and re-use.

Sealed the fact to me that the author is biased towards CSS, without actually knowing anything about CSS-in-JS solutions.


See my new comment just above about DRY. Just because CSS-in-JS lets you re-use styles doesn't mean you should. Re-using styles is often an anti-pattern in large component systems.


> Keeping things 'DRY' and having reusable code rather than constantly repeating yourself is generally considered a good practice in software development. It enables fixes and changes to occur in one place, rather than having to be replicated a multitude of places throughout a codebase. It baffles me then, when CSS in JS advocates argue for essentially the "copy and paste" methodology when it comes to styling.

DRY means different things in different contexts - if you are writing a utility function that is pure and has no side effects, then of course you want to write the function once. The CSS cascade, however, has a tendency to spew side effects all over your application views (e.g. one style that affects a ton of different components), which you then need to override by adding new styles. But be careful, because your new styles have side effects also! Ad infinitum....

For this reason, I regard the CSS cascade as an anti-pattern in most situations. I think that ideally, you want to isolate most of your view specific css to a module attached to the view - so that you are pretty confident that it doesn't have any side effects AND it's easy to know when you can safely delete it. That way you can avoid specificity wars and doing a paranoid but justifiable 'Search in All Files' every time you want to change a style.


What? It's very easy to be DRY in js by copying properties from style modules into the objects containing the styles of a particular component.


Oh stop bashing on CSS in JS already. It's not CSS in JS, it's CSS in component files which are -- surprise surprise -- VIEW FILES. I see nothing wrong with having dimensional and visual definitions in view files, their whole point of existence is to serve as such. You are trying to solve a problem that doesn't exist.


I don't think you've contested any of the authors arguements here. They argue that inline styles are difficult to maintain and refactor, because of the tendency to copy-paste.

Also to implement hover or other styles, you have to go back to CSS or use JS which is much worse.

Also, it's not CSS, it's inline styles, and you lose the cascading advantage. Say I want every anchor tag on my site to be the same color, without CSS I have to go stick that style on every one individually. Realistically you would make it component, but it's a component that wouldn't need to exist with just one line of CSS.

I'm sure it's possible to write in this way correctly, but every time I've seen it it's been awful. But that probably has more to do with the fact that the devs writing it really didn't care much to write clean styles.

I'm not saying CSS is definitively better, that's just my opinion. But if you are going to advocate inline styles you have to know the trade offs and be able to justify them.


> Say I want every anchor tag on my site to be the same color

But you don't. You have a popup calendar component and none of it's links are supposed to be colored at all.

The problem isn't that anyone is wrong here; it's that there are actually multiple things going on here and depending on where you felt the pain last is where your opinion might fall.

I use a lot of 3rd party components that have their own styling and attempting to affect that globally is disastrous for them.

But I'm also rolling out an entirely new style and layout for all our applications and I'm not changing the code -- it's almost entirely global CSS changes.

Sometimes it's hard to reconcile these two things.


> inline styles

It doesn't have to be inline styles. Styled components ( https://www.styled-components.com/ ) inject unique css classes.


Among many other solutions as well (like JSS).

CSS-in-JS !== inline styles, at all, yet seems to be a rallying call for people who fear "something different".


I think in practice, the 'cascading' aspect of CSS turned out to be a bad idea.

Most people seem to find that, rather than providing the consistent theming it promises, automatic inheritance of properties is confusing and unpredictable.

Better to manage consistency through explicit includes of constants instead.


Right, because there is a difference between styling and layout for non-trivial pages. CSS really should have added a "disable cascade" global flag when they introduced variables.

Of course that is how people have been using less/sass for a decade+ now too.


I'm intrigued by this idea that people have been using less/sass for some time now without cascading?


Well, I can see how I implied that, I meant only to say that it allows (and that is how I used it, and the couple times I saw others using it) one to define common properties as variables/mixins and ignore the cascading.

Of course the result is cleanly written style sheets, but the output is a mass of duplicated code.


I see now.

In that case your source code is tidy and the mass of duplication in the output is not so bad while accounting for gzip.

It's best to account for cascading and take advantage of it when suitable. But sometimes a project can just get away from you doing that and you may be better off doing what you're saying. It all depends on the project.

Most of the talk on this page about styling components would result in mass duplication of code. But that might be best for their project.


>you lose the cascading advantage

What? Components and cascading? Only inline styles make sense if we are talking components. Each component must be self-contained, pure and predictive. Why the hell do we want 90s technology again?


This. You can have global styling, or you can have properly-encapsulated components. The more you try to have it both ways, the more they step on each other's toes.

And for me personally, at least for heavy-duty web applications, modular components are far more useful.


You can do component-based, self-contained CSS without inline styles. I would recommend you not use inline styles when it's easy enough to do what you want the CSS way.


> you lose the cascading advantage

while at the same time you maintain the cascading disadvantages. You can't prevent CSS from cascading unless all your styles are inline, or you've OOCSSed your project so thoroughly that you've used classes to recreate inline styles.


The copy-paste problem is true.

But on the other hand, I often end up with a few "primitive" base components that use CSS-in-JS and reuse these components.

So I have a few components with "inline" styles and the rest uses these components.

For a refactor I simply have to change these components.


Yeah I'm really sick and tired of seeing these articles that add no value. Nothing has added more value in front end development in the last 5 years more than using JS for more and more of the view logic so why stop at HTML?


This looks like it was written by someone who hasn't really used a 'CSS in JS' approach. The complaints are actually non existent. Any CSS-in-JS approach is going to have a way to standardize styles across your application.

Regardless, I'm not a huge fan of these CSS-in-JS techniques anyway (although I don't mind Styled Components if I have to use it). CSS Modules, to me, is a far better approach and it sits there in the middleground between 'Pure CSS' and 'CSS-in-JS'

> OOCSS, SMACSS, BEM, ITCSS, and ECSS.

The beauty of CSS Modules is that it basically merges _naming conventions_ like BEM into CSS 'master'. You don't need a convention because the language just sorts it out for you.

Imagine arguing against variable scope in any other language with just saying "hey, just manually namespace your variables!"


Glen Maddern who helped create CSS modules actually went on to help create Styled Components.

Here is a talk he did on his reasoning - https://www.youtube.com/watch?v=MT4D_DioYC8

IMO - Use the tools/tech that make you happy.


Exactly! The basic argument of people like the post author is "Learn CSS, so you don't write shitty CSS". And in an ideal world he's right and I agree with him, conceptually.

The problem is where that ideal meets reality. Few developers bother learning CSS in depth to avoid spaghetti and poor practices, so whether we like it or not - that is a fact and a reality we have to deal with.

That's solved by tooling and/or better languages and better abstractions - which is what css-in-js is aiming to do. Coding standards like naming conventions aren't enforceable enough to scale in real life :(.


This! I feel like everyone forgot about CSS Modules, while I think this is the cleanest and nicest solution to all CSS problems and doesn't make you cringe like CSSinJS or styled components and others.


CSS modules is pretty clean, but disagree that JSS/styled-components are "cringeworthy". They're very powerful, especially when combined with React component props - i.e. let's say when a component has a prop active, that when true we want to change the color on something. A traditional way to handle that would be by toggling some active class, however this creates coupling from the prop to a class, and then the style to that class as well. With styled-components, you can remove one step from that with the classes, one less thing to think about (the developer doesn't need to think what classes are needed with what props, and then what styles apply on those classes).


In practice, DRY in CSS ends up making code very hard to maintain. It creates ghost side effects where you change something on one page and break something on another page unknowingly.

With the exception of a few elements that don't really change at all from one page another like buttons, doing a little bit of copy pasting or search and replace between files is easier.

Sure, you might forget to update one page or component here and there, but at least it won't be broken. Better a component is inconsistent in style but functional than broken.

Using a few variables for things like color and spacing can also help minimize this problem.

Keeping most of my CSS components encapsulated and "namespaced" has worked a lot better in practice than trying to make everything reusable and coupled together in ways that you'll forget about when you have to come back to that project a few months later.


Couldn't agree more. I finished some refacotring of a CSS done with the DRY mantra and there were so many hidden gotchas. When I changed one thing it would end up breaking a number of unrelated things.


Best compromise I've found: CSS modules [1] (commonly implemented with Webpack) which have you write a separate CSS file but modularizes it by exporting hashed versions of the classnames for you to use in your components.

It's the best of both worlds: you don't have to give up CSS tooling like Sass or postcss, but you gain modularity (which is really the only problem CSS-in-JS solves).

[1] https://github.com/css-modules/css-modules


CSS Modules have been revolutionary for us. I agree, it's a great compromise. I don't really see any reason to go to CSS-in-JS from here. It's scaled very well with our team and applications.


> OOCSS, SMACSS, BEM, ITCSS, and ECSS

I've been writing CSS since IE6 and I was a big proponent of BEM for a long time. In the end it didn't cut it and CSS-in-JS is the first time I've actually felt that the CSS problem is solved. To hear "you should be using BEM instead" feels like someone telling me to go back to ES5.


Some developers at my workplace are very resistant to change ("why learn ES6 when ES5 works fine" is a classic line we used to get). Trying to move onto a module based CSS approach (whether thats CSS modules, CSS-in-JS etc), and literally one of them went "but you can handle that with namespaces, why not just do that".

Don't understand why people will willingly do far more work, with more risk, and more prone to error and bugs, than "learn" (using that liberally given how trivial it is to pick up) a modern approach that solves problems for you, so you can get back to making features, rather than dealing with quirks of older approaches.


Every time "separation of concerns" and HTML, CSS and JS come up, I want to scream. I don't think I've ever seen so many people have such a shallow understanding of what a term means. It's practically a trigger at this point.

Everyone who is confused: HTML, CSS and JS are not concerns. They do not represent an intelligent way of separating your application code. Every time you write the ID of an HTML tag, or a component- or feature-specific class name, you are violating "separation of concerns."


I think the phrase "thought terminating cliche" is a good summary of this concept...

I always hear things like separating everything out that way can make it easier for non-technical people to edit the HTML which is rarely going to be a practical idea.

> Every time you write the ID of an HTML tag, or a component- or feature-specific class name, you are violating "separation of concerns."

Yes, you can separate out a lot of the behaviour and presentation between HTML, CSS and JS but there's always some overlap you just can't get away from. Frequently you want to change the structure of the HTML just to make the styling easier for example because there isn't a practical alternative. Jumping around between files to edit the HTML, add a class, styling the class in CSS, modifying the HTML to help with the styling and then adding click behaviour in JavaScript, then trying to figure how it all works again later involves a lot of context switching.


The arguments don't pertain directly to writing CSS in JS, in my mind. Writing CSS in JS doesn't force you to couple your styles to your components, or reuse code or not reuse code, or be consistent or inconsistent with your styles. If anything, it gives you more options.

The appeal of CSS in JS to me is one less language to think in -- one less syntax to worry about and format and lint and forget semicolons in. Also, modules and defining constants. Most web developers seem to use a compile-to-CSS language and a module system these days anyway, rather than vanilla CSS.


Same.

The only thing that intrigues me is that you can make pretty website for the paranoids who run hard script blockers.


How many of people that argument in favor of the CSS in JS know about the Atomic CSS approach ?

It is currently the best of both worlds, you can control it with JS in a proper semantic way (through class setting) while keeping 0% replication and loose coupling between concepts.

It also is easily extensible and composes very well. The downsides are that your CSS file is going to be a bit bigger than usual (tachyons.io with all modules goes about 84KB uncompressed, 17KB gziped). But that can be quite irrelevant in big JS oriented projects where most of the size is occupied by big libs.


If you're interested in this approach, check out Pete Hunt's jsxstyle or Kent C Dodds' glamorous. Both allow you to pass in props that map to css rules (e.g., `<Flex justifyContent="center" />`).


Doesn't it break the separation of concerns ? JSX is already a big red flag in that respect.


The separation of concerns is an illusion anyway. See hacker_9's comment.


So are most things in life. While we want to explain how everything is a different thing let's not forget that breaking most abstractions entails a valid point is being raised. I don't agree with almost all of the hacker_9's opinion, but that is just my opinion, which does not automatically make it a valid opinion.

A single thing covered in names.


What concerns? JSX is for writing UI code and CSS is part of the UI.


And we are all miserably part of your existence. Which does not imply that we should not be viewed as separate entities with different beliefs, desires and ways of reacting/interacting to the noise around us.


An 84K CSS file. Well, I guess that's one way to get fired.


Yes, but that is all the CSS you will ever need to have.

If you assume an average of 2.3MB[0] on the common page, that is about 3% of your project size for CSS that will not grow past that (atomic approach implies that you won't change it as we add more styles to your page(s)).

[0] https://www.keycdn.com/support/the-growth-of-web-page-size/


>> Yes, but that is all the CSS you will ever need to have.

Just make sure everybody else in the company is on board with that thought.


Atomic CSS sounds great until you actually try it on a big project and you run into all sorts of issues. Mostly that your html ends up looking like a total mess which slows down the rest of your work, and that it's not flexible enough.


Most of us know about it, and don't see an advantage to it that outweighs the many advantages of doing CSS-in-JS.


Most apps should have two things:

1) A style guide or component library that is used by both design and engineering for any commonly-used component. In some projects this could just be vanilla Bootstrap.

2) An inline style strategy -- there are now several good options to choose from (Styled components, glamorous, etc). A cool idea here that an engineer on my team implemented recently is using a webpack loader to convert our SASS variables into javascript variables so they can be shared with your styled components.


> A cool idea here that an engineer on my team implemented recently is using a webpack loader to convert our SASS variables into javascript variables so they can be shared with your styled components.

What I do is set my variables in a YAML file and inject those into both my JS and CSS files at build time.


If your solution is "better practices", you don't have a solution.

In the real world, people will migrate to what works for keeping people inline. Appealing to better practice will be mowed down by actual practice. Instead write tools which encourage better practice.


> It baffles me then, when CSS in JS advocates argue for essentially the "copy and paste" methodology when it comes to styling.

This is incorrect. Even if you're using JS for styles you still follow best abstraction practices -- just instead of importing your colors and mixins from another LESS file you're importing them from another JS file. It's no different then designing a styling framework in pure CSS.

What the author is missing here is the biggest single problem with pure CSS -- reusability. Frameworks like React make it incredibly easy to reuse a widget's logic, but what happens when I want to change the styles? JS-in-CSS allows you to do that as part of the widget's API.


Please stop saying "CSS is for appearance, Javascript is for behavior."

Not since the 1990s has it been feasible to write a nontrivial app in which javascript doesn't impact the appearance of a web application.

The real choice is whether one does 50% of the "graphical stuff" in CSS and the other 50% in javascript... Or, instead, one just does 100% of the "graphical stuff" in javascript (independent of the merits of either approach- It may still make more sense to leverage CSS as much as possible, though I'm a skeptic of that viewpoint as well.)


This is like when everyone complained when angularjs put ng-click in the template instead of an .on(click) in the js. It increased productivity because I no longer had to do searches of the codebase to check if there are event listeners. I can just see that by looking at my template


> If you're new to this space, some of the practices to check out include OOCSS, SMACSS, BEM, ITCSS, and ECSS.

These practices sound a bit outdated to be recommended to someone new to the space. Forget any of these and just use CSS Modules, it guarantees you not only namespacing but explicit dependency between your CSS, which most of these conventions -- which require developer effort and compliance -- can't really offer.


There's nothing on caniuse.com about CSS Modules, perhaps you could share a resource?

http://caniuse.com/#search=css%20modules

I don't need any fancy tools or precompilers/processors/etc to use BEM or SMACSS, so I think you may be mistaken about how Css Modules are comparable to the list given.


The idea that a best practice should be usable without a pre-processor has sailed. The fastest people give up on that, the better Web development will be for it.


Are we dumbing CSS-in-JS down just to attack it? CSS-in-JS doesnt mean you have to sacrifice visual consistency or DRY principles. you can still create a central system of CSS properties and import them to be used while being explicit and scoped about the stuff that is not shared. I feel like this is being debated more than its worth. As with everything, pick the right tool for the job.


amen


There are concerns with CSS in JS, but the arguments in this blog post are all very weak or non existant.

Structural/Behavioral Vs Graphical

The introduction of component based tools changes how we design and build our application. No longer is the fact that you can wireframe your whole application valuable instead being able to build individual components and later compose those is valuable. This means that the graphical properties being tightly coupled to a component is actually good.

Loose coupling vs tight coupling

Component based systems can be built with loosley coupled components, but that doesn't mean the components themselves should loosely coupled to their own implementation. This is more analgous to the native platforms too.

Visual Consistency

Claiming that CSS in JS produces visual incosistency is about as true as claiming that CSS does the same. In both cases you can be more or less inconsitent based on your chosen implementation method. In both cases you can move the lowest level design tokens[0] to a single places/system. Arguably Javascript being a more expressive programming language is actually better at achieving consistency via the more powerful variable system.

Code Reuse

Again with a design token system in place changing the design language etc is as easy as changing a few variables.

Personally I think the more interesting problems with CSS in JS is the inability to extract the CSS out into css files to be shipped along the application and how that pertains to server side rendering.

0: https://developer.salesforce.com/docs/atlas.en-us.lightning....


The issue with shipping server side CSS is solved in frameworks like styled components too.


> Rather than being tightly linked to structure, these are very loosely coupled - this is why one can often wireframe an entire application out before styling it!

Here's one of the premises on which the article was written - and I must wholeheartedly disagree.

If you're looking to write clean, maintainable CSS - you MUST consider DOM-structure of the thing you're styling as well. Too often, quirky CSS selectors are written, only because someone failed to foresee how HTML and CSS work together to create a visual.

This decoupling of the HTML that's written, and a CSS "theme" being written/applied after the fact, is also where things like negative margins (ugh) and the like tend to come from.

Now, I've been working on a very large component library in React, and keeping our CSS maintainable has not been an issue. We've got one (S)CSS file per component, and it resides in that component folder.

And while the file is separate, we absolutely do not allow anyone to develop any component anymore, without having any knowledge of how to style the thing.

We used to do exactly that: other devs would develop component, we would try to style them afterwards. This always results in either us writing messy CSS with crazy selectors or - and more often - we simply opted to re-write the entire HTML, to suit our styling needs.

At this point in time though, I would love to write some CSS-in-JS here. Too often we need to use variables based on JS logic; And it ends up as an inline style right now, anyway...

All in all, if the writer believes HTML and CSS can be written separately, without resulting in a terrible mess, I'm having a lot of difficulty accepting that they know what they're talking about. Sounds like they never had to work on, or maintain, a large application.


https://github.com/styled-components/styled-components

strikes a really nice balance here imo. I use Radium every day and in general it has been easier to maintain and use in comparison to all css but if I could do it again I would go with styled-components.


"As the lead for ZURB Foundation, I've trained hundreds of people on frontend frameworks and best practices."

Ok, this kinda explains everything.


Funnily enough, it's impossible to properly style many of ZURB's components, as their CSS is tightly coupled with the DOM


Most of the author's concerns about reusability, maintainability, and separation of concerns can be addressed by thoughtfully structuring your JavaScript application project. For example, using React/Redux and JSS, the JSS (a CSS-in-JS technology which uses CSS modules among other things) goes in the "dumb" component files, not the "smart" (or "linked") container components which pass Redux state and various functions to the "dumb" component. And then creating a styles.js file (or multiple files if appropriate) is a simple way to create shared JSS styles which can then be imported into various component files as needed.


Very readable article. My favourite line:

> Please enable JavaScript to view the comments powered by Disqus.


I agree that often times CSS-in-JS forfeits some of the expressive power that makes CSS powerful, in the attempt to gain some muscle from JavaScript.

Instead of CSS-in-JS I think a better pattern for extending CSS with JavaScript is 'event-driven virtual stylesheets', which I call JS-in-CSS.

I'm writing a website dedicated to JS-in-CSS techniques, plugins, and theory. It's still a heavy WIP right now, but there are ~20 plugins that can be used and code samples and links to their documentation which is good to go already: http://responsive.style/

I'm trying to write down and share the results of what I've found trying to combine JavaScript styling with CSS for years, and the patterns and techniques that make the two useful.

You should be able to take full advantage of 100% of CSS's expressive power _and_ still augment it with JavaScript logic. You can have the best of both, and this JS-in-CSS pattern works in every browser you can imagine (I recently got it working in IE7 and IE6 just for fun!(


I think the best answer to this is three questions.

Is the browser being used to make dynamic "apps" instead of static web pages?

How do app frameworks/toolkits on other platforms style their apps?

And finally:

Do you think the people who designed all of those frameworks were stupid?

Seems to me like the web is finally catching up with the only sane way of styling the widgets in an app. It's done in the same language and it's per component/ widget.


> JavaScript used to do this, and we fixed it by encapsulating everything in modules and using tools like webpack to stitch everything together.

We've done the same with CSS, and CSS modules work extremely well. For us, they've even eased the need for SCSS.


I have started using and evangelizing styled-components in our react projects. Hard to explain, but it just feels like it is the right way to do CSS. Having everything to do with the view for a component in one file works well for the way I work.


CSS is for a print paradigm. But it makes very little sense in a web app paradigm. So in lieu of anything better, we encapsulate CSS with hashes, and write it in Javascript so we can have dynamic styling.

What we really need is a better way to style web apps.


I've been trying out CSS modules in my new project. I've also set up a library that generates Flow type definitions, so I get static type checking and autocomplete for my CSS classes [1]. It's pretty awesome, and works with SASS too. I love having every React component self-contained. It makes refactoring and reusing code so much easier.

[1] https://hackernoon.com/type-safe-css-modules-with-flow-dd95e...



Why can't people just not go out of their way to write crap CSS in the first place?

There seems to be this trend to show off all the possible different ways you know of addressing a single element somewhere, by pointlessly combining them together in brittle ways that depend on each other and accidental document structure, using haphazard random inconsistent naming conventions.

If there's only one of them, then use a fucking id.


Context: I work on a large CMS powered site

We have a company wide rule of no IDs in styles - we actually lint for them. As a front end team, we can't be certain that there will only ever be one of a component on a page at a time. Sometimes we can be mostly certain, but the content authors can theoretically do anything, and our job is to provide them flexibility whilst keeping the site looking good.

Modular CSS would be a God send for us, would be able to handle a lot of things much cleaner but sadly the current build of the CMS doesn't allow for it.

In small sites, or anything with static content, IDs are more than valid. But it becomes a lot harder when dynamic content, especially dynamic components, come into play.


^this. If people took the time to learn the basics then this whole thing wouldn't even be an issue.


> The Real Answer: Better CSS Practices... > If you're new to this space, some of the practices to check out include OOCSS, SMACSS, BEM, ITCSS, and ECSS

This is not a real answer. It's an attempt to fix the broken screwdriver with ducktape, bird poo, and spit.


But that's how web apps are built.


It is. But it's not the real answer.


'Broken screwdriver?'

Don't get OP's analogy. Does he mean CSS?

While CSS can sometimes be nerve-racking it's the most modern layouting system. There was a reason that the React Native team chose CSS' Flexbox for their layouting system.


This article is a little bit flawed and a little click-bait-y also.

CSS-in-JS is more or less enforced-CSS-modules + some sugar + a different way to author your styles.

Most of the arguments there are against CSS modules, or “isolated styles”.


And it does a poor job in that regard too.

- CSS modules promote more re-use if structured correctly - BEM and the like exist to do the literal opposite, to isolate styles to minimise regression and site wide issues at scale.

- Visual consistency is enforced in CSS usually through variables to make sure spacing, colours etc. are the same, with a default set of global styles. There is literally no difference in a modular approach - you can easily have global styles to theme, and then isolate and import the more specific rules as needed.

This article reads as "I learnt how to do CSS this way so anything new is scary and wrong"


> This article reads as "I learnt how to do CSS this way so anything new is scary and wrong"

Yes. A little bit sad…


Very well-put! In trying to solve one problem, we create tons more. So much more added complexity! The React stack is growing out of control with the flavor of the day changing daily per se!


Like religion there's no one true way but I hope people agree that using analogies in technical discussions adds to confusion and is best avoided.


The Shadow DOM solves all of CSS's scoping problems.


What's wrong with web components? They solve the problem very elegantly, and thanks to Polymer and others we can use them today.


I even use CSS in JSX, while some people would consider JSX alone madness already, but it feels really nice to write it that way.


Tell that to ReactJS devs, those mad men include even HTML in their JS files, how insane do you have to be.


not all CSS is equal: if you define global styles like h1{color:#000;} you want them outside components, in components you want the minimum of css needed to render correctly your date picker or whatever you are trying to accomplish and you want minimize external dependency on the global css.


I have highly been enjoying "CSS" in JS with React and things like Radium and AphroditeCSS


LESS/SASS takes care of this with nesting (ie. scoping css rules).


I've worked on many different codebases. CSS and script tags add to the mess something awful. For cleaning CSS I take an existing site open with developer console and click through every HTML element in the tree looking for alignments offsets, centering madness before flexbox, font size and color corrections are all stripped away. These settings belong in the top level body or global part of the CSS. I flatten out the HTML and CSS alike so all my elements are at most 4 levels deep.

This is a process that takes about 1 day per product page. It's a horrible pain to clean up a site but the payoff is easier maintenance in the future and hopefully some acknowledgement that the page loads better. This skill can easily be trained in to developers. I hope this reminds everyone that computing is a skill that must be practiced.

It isn't normal to use tables for layout these days, just like it is no longer normal to use JavaScript for centering elements vertically. This is fixed with flexbox. Please learn and use it!


Try doing this in a team of 5-500 developers continously adding features all over the site.

Then try adding an isolated component in a sidebar somewhere with 0% risk of visual regression elsewhere.


HEY LOOK, NO ONE CARES ABOUT YOUR PROBLEMS! http://caniuse.com/#feat=style-scoped


Image macro memes in 2017 is like putting fingers down my throat.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

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

Search: