18 ms·
Why I Write CSS in JavaScript
- mxstbr 8y agoAuthor here, happy to respond to any questions. AMA!
- CiPHPerCoder 8y agoHow do you plan to accommodate NoScript users?
- ervine 8y agoYou generate a css file with something like webpack.
- mxstbr 8y agoDuring server-side rendering CSS-in-JS returns a <style> tag with all the CSS inlined. If you do not server-side render, it does not matter whether you put your CSS into JavaScript or not—your JavaScript app is not going to render anything anyway.
- osrec 8y agoI know this will be unpopular, but after a certain point, noscript users just get a bad experience and that can't be helped. If a developer wants to provide a rich experience, then there will always be certain platform requirements. Without them, you will have a lacklustre experience. It's like saying "I want to have all the whizzy functionality of your app, but I want to access it using a standard, run of the mill, mud-laden potato" - it's just not going to be possible.
- deleted 8y ago[deleted]
- dictum 8y agoI know how the sausage is made, so I know that making a full web app work without JS isn't at reach for most teams/products. By knowing how the sausage is made, I'm also aware that the line marking the aforementioned certain point is often drawn too early, at informational (i.e. document) stuff where HTML and CSS are fully capable on their own.
- osrec 8y agoYou underestimate developers; they can make it work without JS if they have to. But why should we constrain ourselves?! I mean, there is nothing wrong with JS when used properly. In fact, JS is extremely useful in the browser. It adds to the richness and interactivity of webpages. We must collectively appreciate this, and stop denying this! Even HN is a better experience with JS. Some sites do give JS a bad name, and poorly used JS is something I hate too, but JS as a concept is something that I wholeheartedly support. Thankfully, the web is mostly opt-in - if you don't like the way a site employs technology, just don't visit it. Simple.
- madeofpalk 8y agonoscript users certainly signed up for a subpar internet experience, but its not just them that should be thought about. Slow internet connections are a reason to think about the experience when loading JS is slow and/or failed. It's not just 'poor people' who have slow internet - 'rich people' on inflight wifi or on the internet on the train can result in things not loading.
- osrec 8y agoThere isn't much that can make an in-flight connection seem quick, but we've tried with our PWA (https://usebx.com/app https://usebx.com/app) and to a certain extent, succeeded. Ok, we do assume that you have visited our webpage at least once in an area of strong signal, however, once you've done that, all the JS is cached and all we transmit back and forth are lightweight, gzipped json payloads, often less than a kilobyte. I use my own PWA regularly, and found it actually quite usable in-flight.
- thedaemon 8y agoI think this is a big issue with such JavaScript and load heavy web-sites & apps. They forget that they have users without 1GB connections and who can't afford, weather financially or location based, the download the 500MBs of data required to load their web-site. That and hiding CSS inside of JS feels like a sneaky tactic to keep people from editing it? Or does it actually create the CSS on the fly? I wasn't quite sure after reading the article.
- ringaroll 8y agoNo regular JS only website/app required 500mb of data. Please stop exaggerating. It does not make your point valid.
- yodon 8y agoNoScript users are almost always economically irrelevant to the business posting the page. They tend to be extra aggressive blockers of ads (and therefore ad revenue) and are sufficiently far from the center of the bell curve technologically that they are both a tiny minority and their product needs and wants tend to be edge cases that are not economically efficient for the business to pursue. I get why NoScript users want to run NoScript, but it's the most powerful signal a web visitor can provide a business to say "focus your resources on the needs of others ahead of mine."
- davnicwil 8y agoReact apps have to be deliberately engineered to work without JS at all, via server rendering. Assuming that's done though, the CSS in JS can just be server rendered too. It's rather easy too if you're using a (great) library like styled components - this functionality is built in and just works with a couple of extra lines of code. The deeper question here is will the app work at all without JS. That's quite hard to achieve (every client side interaction must have a server rendered equivalent accessible via a url or url params, essentially) but the CSS part is easy.
- bfrydl 8y agoThe only reason I know of to bother supporting NoScript users is so that when you announce your site on Hacker News you don't have to read that one angry privacy guy talking about how bloated your site is because it requires 200 KB of JS.
- ggregoire 8y agoDoes he need to? I know my users don't use NoScript.
- bastawhiz 8y agoIt doesn't really matter how the JS components are styled if NoScript users aren't loading JS, though I assume you know that and are just trying to make a point that sites shouldn't be using JavaScript.
- ringaroll 8y agoThey're economically irrelevant so they're ignored. Their demands tend to be edge cases. NoScript users are like the customer that demands the most but pays least. After some rants of such customer, they're ignored.
- kowdermeister 8y ago- Were there moments when you cried back SASS or vanilla CSS? - In your react example, I see you created <Title> as styled.h1, but that's an awkward way of bootstrapping a component. Even if I used SC, I would still put the style information outside my component code in the same directory. At this point I don't see the benefit over doing something like: import * from './login.scss'; What can SC do that regular CSS or SASS can't?
- ervine 8y agoThe big win for me is if you're making an SPA, all the knowledge of the app state is already stored in JS (redux, or local state, or handed down as props if using React). So instead of toggling styles on a class, you just hand the state to the styled component, since it's just a function that returns css.
- kowdermeister 8y agoToggling styles is a good question. I have sometimes multiple classes that have to work together. For example to open a panel, I use some translate/transform, different positioning. How do you compose different styles for a single component? How do you deal with mobile, where sometimes I have to override dozens of declarations with media queries?
- mxstbr 8y ago- No! I have not missed class name collisions and specificity wars at all, and I have enjoyed being able to dynamically adapt my styling as necessary. - This ties into a broader point of having "style components" like <Grid /> and <Row />, which is a very nice way of working in React. styled-components (the library) simply takes that pattern and enforces it across your application. See style-components.com for links to some more resources about this pattern!
- pbiggar 8y agoCan you say how this affects the classes and ids you add? I'm guessing you use classes and IDs a lot less because you don't need things to match the css against?
- akuji1993 8y agoHonestly, I think the CSS-in-JS approach is not for me and we haven't used it except for times where there was no other way to do something. Instead we have used CSS Modules (https://github.com/css-modules/css-modules https://github.com/css-modules/css-modules), first by including it manually in webpack, now it's already built into create-react-app so I just have to install node-sass and call my Sass files ComponentName.module.scss and I can use them the same way in my .tsx/.jsx files that you use CSS-in-JS. IMO that's a lot less messy and makes your jsx files smaller and better to read. Also it's easier to write Sass and have the pros of that language on top. Did you consider this approach at all and what did you not like about it?
- daliusd 8y agoBonus point: you get hot reload while editing CSS.
- exogen 8y agoWhile different from Styled Components, many people still consider CSS Modules to be squarely in the realm of CSS-in-JS. It literally generates a JavaScript module that you must import into another JavaScript module in order to actually use the CSS classes you write, after all. Having some experience with CSS Modules myself, I thought they were interesting and definitely an improvement, but still left a lot to be desired. For example: needing to use a helper like `classnames` to join/toggle many dynamic classes together was very ugly and cumbersome. There is also no way to "directly" tie variable state/props to CSS rules – you're still required to use this indirection where a state/prop relies on there being a predefined class/modifier in the CSS file. e.g. font-size: ${props => props.size}px; color: ${props => props.special ? 'red' : 'blue'}; With solutions closer to the "fully JS" end of the spectrum like Styled Components, there are no extra "modifier" CSS selectors to come up with to handle the above situation.
- Touche 8y agoWhy do you think CSS-in-JS has only caught on in the React community?
- chooseaname 8y agoHerd mentality. RDD (resume driven development). Cargo culting. Ooooh shiney! "I'm not confident enough to make my own decisions, so I'll let the 'community' decide for me."
- dmitriid 8y agoProbably because it's the only one among major popular frameworks that doesn't use weird compile-to-js templates, and relies on JS only. Others (I'm thinking Angular and Vue) have their own templating systems that they compile to JS anyway.
- daniel_warner 8y agoYour reasons sound similar to those given for standardizing on in-line styles as much as possible. Both methods are ways to subvert or work around the cascade. I would like to hear from you why you think the cascade works the way it does, and what aspects should be preserved so as to not 'throw the baby out with the bathwater' while adopting these new methods. Thank you!
- iSnow 8y agoHonestly, it sounds like you now have a write-only site, as you will have a hell of a time 5 years down the road when the CI changes. Personally, I find the Vue.js concept much nicer, but even given that, I define my styling in LESS (SASS...) to benefit from inheritance/mixins on the level of styling. Semantic approaches like BEM or Bulma make a lot more sense to me. It seems to me React has made a feature out of a flaw, much like the intermingling of code and HTML back in the days with ASP/JSP/PHP.
- woah 8y agoBEM is just a weird hand-cobbled way to add scoping to CSS
- therealmarv 8y agoIn my opinion this is a workaround for a language flaw in the React concept. Look at this beauty for comparison: https://vuejs.org/v2/guide/single-file-components.html https://vuejs.org/v2/guide/single-file-components.html
- dsego 8y agoYup, that's what you can have with precompiled templates. Riot.js introduced the same concept of scoped css years ago, I wish it was more popular. On the other hand it goes against the "it's just javascript" concept of React.
- akuji1993 8y agoHm, I don't share your opinion on this matter, to be honest. You can easily avoid this in both Angular (which does it out of the box) and React by including CSS Modules (https://github.com/css-modules/css-modules https://github.com/css-modules/css-modules) which, if you use create-react-app to build your projects, is a 5 minute change to your architecture. So there really is no reason to write that down as a con for React.
- scottrepreneur 8y agoWorks out of the box for the most recent version of CRA, as well.
- dictum 8y agoYou're right, but community support around a certain pattern often makes it the de-facto practice, so defaults matter even for a non-opinionated library (where "defaults" are essentially what tutorials and thought leaders point to)
- cynicalreason 8y agoI always thought css-modules is the de-facto practice
- 8y ago
- denysonique 8y agoWhile Styled Components, Styled JSX or Linaria (which doesn't require a JS runtime for production) are nice solutions, the fact that I can no longer use the colour picker and other tools to live edit CSS from the styles pane in the Elements tab in Chrome Dev Tools, sometimes makes me want to go back to plain CSS to get this functionality back.
- jakelazaroff 8y agoYou can! I do this all the time.
- kowdermeister 8y agoWith copy and paste? :)
- jakelazaroff 8y agoAm I misinterpreting something? In my app that uses CSS-in-JS, if I go to the "Elements" tab of my browser developer tools and select an element, I have the option to inspect, add, remove and change styles — including using the color picker and bézier curve editor — and have it reflected live on the page.
- leerob 8y agoWhen my styled-components app is in prod, the styles are non-editable. When developing, I can use Chrome Dev Tools. On prod, I have to copy paste. Maybe I'm doing something wrong?
- exogen 8y agoI believe this is a result of it using the "CSSOM" browser APIs for speed in production. Unfortunately, browsers apparently haven't figured out how to make such styles editable yet. It's definitely a limitation of certain CSS-in-JS implementations, but unfortunately one that inherently comes from "using the platform."
- bpicolo 8y agoCSS in JS is one place where Vue has a substantially better experience. Being able to toss scoped-css, written as normal in a css block is what I call nailing the developer experience. It is all the best parts of css in js with none of the downsides.
- cageface 8y agoYou can do this with styled-components in react too. https://www.styled-components.com/ https://www.styled-components.com/
- preommr 8y agoYea, but this isn't out of the box. This is some 3rd party solution for a pretty major part of an application.
- apazzolini 8y agoI understand your preference for frameworks, but I actually appreciate that it's not out of the box. I'd rather have libraries focus on one thing and do it well - the Unix philosophy. This lets me compose the appropriate libraries for the problem at hand.
- iaml 8y agoYou are complaining about react's philosophy itself, which is they don't want to make any choices for you.
- FiddlyPack 8y agoAngular also does this, fwiw. Also allows you to manipulate the styles from DevTools which I hear is a problem in CSS-in-JS
- bpicolo 8y agodev tools works fine with both react and Vue if you set it up well, meaning to extract css to a file instead of throw it inline. Most setups extract to a file
- cryptos 8y agoThe problem with orphan CSS is adressed very intuitively in Vue.js with single file components (HTML + JavaScript + CSS). https://vuejs.org/v2/guide/single-file-components.html https://vuejs.org/v2/guide/single-file-components.html
- vehemenz 8y agoHow do you handle advanced CSS Level 3/4 selectors, CSS grid, and media queries?
- bastawhiz 8y agoThe idea with CSS-in-JS is that you don't use selectors. Since you are constructing DOM nodes individually, you don't need to select them. Styled components can accept props, which lets you style dynamically (e.g., using an array index to replace `:nth-child`). With regard to media queries, it depends on the library. For the library the author is using, the media queries are defined inline: https://www.styled-components.com/docs/advanced#media-templates https://www.styled-components.com/docs/advanced#media-templa...
- GordonS 8y agoDoes it use (shared) variables, like with SASS? With SASS, I find it really convenient to define variables for common/brand colours, for example.
- bastawhiz 8y agoYou can define a "theme" object, which you can inject into your styles (with an expression inside the template literal). Other libraries support variables more directly.
- addedlovely 8y agoYeah or pseudo elements / hover / focus etc?
- exogen 8y agoPeople often confuse the two, but CSS-in-JS is a distinct concept from "inline styles" (which can make pseudo selectors more challenging). Almost all CSS-in-JS solutions (including styled-components mentioned in the article) still support pseudo selectors, media queries, etc.
- 8y ago
- LocalPCGuy 8y agoI understand the "pit of success" idea, particularly when it comes to more junior devs. But I don't necessarily agree that you need stringent processes to get most of the gains you cite from using something like SCSS or even regular CSS these days. It's really easier than ever. 1- append only? No, each module/feature/widget gets its own CSS file, imported to the main app CSS file. Delete the widget? Delete the file. 2- Specificity issues? Never use IDs, stop using tag names and simple classes and adopt a simple naming structure (doesn't have to be BEM, it could literally be ".widgetName-header") Since I adopted those 2, I've almost never had dead CSS from deleting features or collisions in my CSS. I do still have a small base set of styles that are shared but it's small enough to be easily manageable. 3- dynamic properties? CSS variables. Not an option? Child classes that apply the dynamic styles serve most use cases. Truly dynamic styles are rare, in my experience. I'm still keeping an open mind about the possibilities, but my strong opinion (weakly held) is that I still don't see CSS-in-JS as more of a bandaid for people that like CSS and (for many, not all) those that don't have an in-depth understanding of it.
- arethuza 8y agoIn case anyone else was wondering what BEM is: http://getbem.com/ http://getbem.com/
- ggregoire 8y agoThat's also what we do here on a dozen of apps and it works. Each component has its own folder with its own css file and each rule starts with .name-of-the-component. For dynamic properties, we either create conditional classes (e.g. 'success', 'error') or pass the rules through 'style' (e.g. dynamic height). For dynamic themes, we create an object at the root of the app const theme = { header: { backgroundColor: black }, button: { backgroundColor: black }, ... } Then pass it down to the related components <header className="default-header" style={theme && theme.header}> <button className="default-button" style={theme && theme.button}> That being said, I tried styled-components once and don't really have negatives about it. It's a viable option.
- qudat 8y ago> Delete the widget? Delete the file. This rarely happens. I would argue that creating an automated system to enforce "rules" should be favored over forcing every developer to know the rules and abides by them. It is much easier to understand the relationship between css and js when the css is just a js variable. Having built many large applications using the CSS file method, css modules, each widget gets its own file, co-locating css files with the js, I much prefer using `styled-components`. It provides a ton of flexibility, it opens doors for dynamic css by leveraging js (the hacks I've seen, had to write to get css dynamic is astounding), and I don't have to look very far to see how it's being used because the CSS is literally attached to the component I'm using. All I do in VSCode is cmd+click and bam, I can see the CSS for this component. There's no need for naming convention, there's no worry about global css variables getting into your styles, and there's no digging around looking for css that might be influencing your component. The best part for me is: when I delete the component, the CSS is gone as well. There's no thought put into scouring the FS to find lingering CSS that used to be used. I love `styled-components` and most of the designers I work with also enjoy it.
- antoineMoPa 8y agoThe down-side with this is very high coupling between UI logic and style. If style becomes out of fashion, you have to modify files that contain logic. If framework (react/vue) becomes out of fashion, keeping styles will be difficult. The other down-side is thousands of web developers having to re-learn CSS and the tooling behind your app instead of just changing CSS files.
- tobr 8y agoIn practice, I think a lot of people have found that you can rarely do a complete overhaul of a website’s design using only CSS. Even if you could, it would be impossible to feel confident that your changes look reasonable across all uses of said CSS. So if you’re doing a big redesign you will usually have to work with logic anyway. I think there’s truth to your second point though - reusing styles in parts of a project that does not use the same framework. Something like Tailwind CSS can be a good option then.
- gedy 8y ago> you can rarely do a complete overhaul of a website’s design using only CSS Full design yes, but branding/theming is much easier if you use an external styling framework like Bootstrap 4 or Foundation and use their component and utility classnames. We have a 300+ page app and tried the one stylesheet per component thing with theme and layout all combined in the past, and was a huge mistake. Banning most custom CSS in place of using the Bootstrap component and util classes has been so much easier.
- antris 8y agoYour styles are coupled to your UI logic anyway, even if you go out of your way to make them implicit by separating the CSS and JS into their own files. It's better to have the relationship explicitly defined in code instead of hiding it. That's the whole reason why CSS sometimes breaks in unexpected ways: you fail to realize the implicit coupling of the styles and the UI logic, so you fail to reason what changes need to be made both to styles and the UI logic to make your change.
- realharo 8y ago
- brianzelip 8y agoOff topic, but I really like the new site design, particularly the Appearances page!
- lousken 8y agoIf you make sure your site works without javascript as well(unless it's actually an app) it's fine by me.
- zeroname 8y agoThis is a requirement that most sites can simply dismiss these days. The distinction between an app and a website is blurry, a lot of interaction simply works far better with Javascript. Supporting "no Javascript" can be costly. It's possible with server-side React and careful engineering, but why bother? What's the impact on the business?
- treerunner 8y agoBother for human rights. "Javascript" is costly too - but maybe not your concern since it's not a business cost.
- zeroname 8y ago> Bother for human rights. Which human right, specifically? Humans have the "right" to install a modern browser and enable Javascript. > "Javascript" is costly too - but maybe not your concern since it's not a business cost. Indeed, the cost you pay to run Javascript does not show up in my budget, just like I don't pay your ISP to serve my site to you.
- lousken 8y agoI don't know what the real impact is, but if your site shows me blank page without javascript(I have it off by default) I am closing the tab. I don't think supporting noscript version is costly because for me that's how it supposed to be by default. 90% sites that are currently on the internet would work just fine without any js and 95% would work with as little as hackernews has. Modern CSS allows to create most of the experiences and unless you need some interactive forms or serving live broadcasts, games etc., there's just no point in using javascript. Over the years I've stripped javascript from about 40sites which I visit daily without sacrificing any real functionality. Those sites download and render visibly faster, only relevant cotent is shown and I even implemented dark theme for them. My only javascript fixes are for broken galleries or embedded videos (and those wouldn't even be necessary if developers wrote a fallback to noscript). It used to be that developers loaded many little scripts so I could only block the useless crap but since everything is minifed and bundled in one huge unreadable file, I just use uMatrix to block it entirely and Stylus and Tampermonkey to fix it.
- maaaats 8y agoI've been using elm-css on a project lately. Pretty cool with typesafe CSS. Also inline, but since everything is functions it's easy to compose/reuse as well when needed. (Compared to the string templating shown in this article)
- martin_a 8y agoThis sounds like an awful idea. Just put your CSS in a .css file where it can be cached, delivered by CDNs and can easily be edited in a single place. Separation of content and presentation has been around for a good reason. One should always avoid mixing logic and design because it will break some day, no matter how well you think you handle it.
- ggregoire 8y ago> Just put your CSS in a .css file where it can be cached, delivered by CDNs .js files are cached and delivered by CDNs too. > can easily be edited in a single place If you change the name of a class (or add a new one, delete another one, edit the structure of the component, etc...), then you have to open and edit 2 files. With author's solution you don't. The CSS is collocated with the component. > Separation of content and presentation has been around for a good reason. One should always avoid mixing logic and design Author is talking about putting the React component (presentation) and its CSS (presentation) in the same file. He's not mixing business logic and design.
- pmlnr 8y ago> .js files are cached and delivered by CDNs too. Not in 2019, in the age of excessive A/B testing, where every page load gives you a different set of JS.
- beefalo 8y agoIf you need caching then you would likely server render your page and that would inline all of the critical css to be cached as well. Writing your css in JS files also does nothing to prevent you from separating content and presentation. You can write components that just handle styling. I see more problems with separation in css where you end up with one giant file that handles the whole site.
- Yabood 8y agoWe built a relatively large social media management platform, and for one of our major features (a streams page that shows social media activities from different sources), we put a lot of our css in JS including all the logic for stream sizing/resizing and page responsiveness. I can honestly say that this approach is terrible. It is a maintenance nightmare. Even the smallest changes require a ton of time. We're now rebuilding the page from the ground up because it has gotten so messy, no one on the team is interested in touching it.
- therealmarv 8y ago... especially web designers.
- pluma 8y agoWhat are you trying to say?
- loz220 8y agoPoorly designed code is possible with any language. Was it unmaintainable because of something fundamental to css in js?
- abderrahmane 8y agoWhy can't we see more of these stories surfacing on the internet. All I see when I search for CSS-in-JS on google is how, CSS-in-JS is so great. Why don't we have more : "We tried it, it is the worst, especially for products which lifespan is more than two months"
- black-alert 8y ago> Why don't we have more : "We tried it, it is the worst, especially for products which lifespan is more than two months" Because that last sentence is just rubbish, CSS in JS is great. I'm using it for large projects already 4 years. If your experience is bad you must be doing something wrong. CSS in JS is almost the same as working with (S)CSS, except for extra power to control dynamic elements without having to juggle with classnames.
- deleted 8y ago[deleted]
- benologist 8y agoI write CSS in CSS and my JavaScript in JavaScript because at some point abstractions pile up into this massive cognitive burden for anyone adopting your code, especially when they didn't follow the exact same path as you technology-wise or if they're newcomers. I want my work to be pick-up-and-play, not RTFM x 20 abstractions and tools.
- pitaj 8y agoEven if there was more cognitive burden, it's insignificant compared to the drastically reduced amount of context switches the developer has to deal with.
- pmlnr 8y ago> Why I Write CSS in JavaScript tl;dr because it's convenient. It's also redundant, goes completely against the features of CSS (the cascading part), doesn't utilize the possibility of selectors, children, etc, ugly, and computationally heavy. But yeah, why not.
- zeveb 8y agoNot to mention that it doesn't work without JavaScript enabled on the client (unless he's generating CSS in server-side JavaScript). That's fine for a true web app (and web apps do have their place), but it's completely not fine for a web page, which should display just fine without JavaScript. People should not be forced to grant you permission to execute code in order to read text & view images.
- LaserToy 8y agoCSS... sweet memories. For some reason I never was able to learn how the damn thing works. I worked for Google Analitics in 2011 and we rebuilt it using new in house built framework which championed an idea of a separate styles for an on screen component. Every dev was starting a new component with: clean_styles directive as nobody was brave enough to deal with what comes from the top. Even though it was possible to use cascading part, nobody was brave enough to own styles for the whole product. So, We ended up with so many styles we had to split them in couple files as we reached a limit in IE on number of styles in one file. Last time I checked GA is loading 3 of them... Is it a time for some other way of doing it?
- LocalPCGuy 8y ago> I never was able to learn how the damn thing works People not taking the time to learn is not a reason to throw an entire building block of the web out. (Yes, I realize there are a lot of people who know CSS and still choose CSS-in-JS, but I'm specifically referencing the point re: not learning CSS.)
- LaserToy 8y agoI didn’t say I did not spend time, I said - could not. Same applies for most people in the team. I think we had coupe folks who were spending a lot of their time explaining CSS. My theory is that CSS was something that was treated as a task. Make a lot of client/server side development and then make these freaking lines align perfectly. So, most of time engineers were avoiding styles, applying them was the most tedious and hated part of the job. And it is hard to be good at something you hate.
- LocalPCGuy 8y agoI agree with you re: the task comment, there is a difference between JavaScript developers and Front End UI developers. It's almost like the full stack discussion but just in the front end ecosystem.
- 8y ago
- jmull 8y agoI'm unconvinced. For one thing, it's not CSS in Javascript... there's no cascade and no sheet, so it's just "styles in Javascript". (And, actually, this article is only about a specific implementation.) The benefits listed are: - "confidence" - but I think that's a matter of understanding and mastering the tool, whether it's CSS or this library. As the co-creator of "styled-components" the author is no doubt a master of it. For for the general developer, perhaps a roughly equal effort would provide a similar level of mastery in each. So why not invest in the standard? "Painless Maintenance" - I would have to use it deeply before I could say too much about this. But I would guess that the danger of creating spaghetti code and a spaghetti of .css are pretty much the same and have the same root causes. "Enhanced Teamwork" - I don't see the connection here. The discussion in this section seems to be about mastery of the tools again. The team can learn how to manage styles though CSS-based techniques or they can learn through techniques based on coding Javascript and the capabilities of this library. Not that CSS doesn't have its issues. IMO, it's too low-level to use directly for many cases. There are two main problems: (1) missing the tools to manage complexity, like scoping, variables, and modules. (2) allows you a lot of freedom to do bad things. But there are libraries that address these that don't throw out the fundamental design of CSS, as styles-in-code does. To me it seems like a better approach to build on CSS to address its weaknesses rather than throw it out. The design of CSS itself came out the recognition that the tight coupling of style and content has drawbacks, and this is signing back up for those drawbacks. And you better neatly divide your presentation code from your business logic code and data access code or you'll get all that coupled tightly as well. I'm not dismissing this out-of-hand -- I haven't dug into styles-in-code approach so I don't have a deep understanding of it. But I'm not convinced it's worth the time to look more closely at it. Really, not even close.
- jancsika 8y ago> "Painless Maintenance" - I would have to use it deeply before I could say too much about this. But I would guess that the danger of creating spaghetti code and a spaghetti of .css are pretty much the same and have the same root causes. But as you pointed out, there is no cascade and no sheet. The styles apparently just apply to the stuff they are near in the code. No twisted logic to unwind, hence no spaghetti. The potential problem I could see is that changes which would have been easy with a cascade would require lots of changes to copypasta in this approach. Like, "take the spinach out of this ravioli and replace it with mushrooms." Everything is scoped properly and the task is obvious at a glance-- it's just annoying.
- err4nt 8y agoI've been doing almost the opposite - enhancing and extending valid CSS stylesheets by using JavaScript to define new features and functionality to be made accessible and usable by writing valid CSS. An overview of my tooling and workflow is here: https://github.com/tomhodgins/caffeinated-style-sheets https://github.com/tomhodgins/caffeinated-style-sheets The big idea being that CSS should be able to apply to _any_ HTML, no matter how it was created before it got to the browser. Many style-related tools integrate tightly into your framework or into one particular workflow but don't give you the flexibility you need to apply any styles to any website unless it happened to be put together with specific tools a specific way, but I don't think that provides enough flexibility.
- jpochtar 8y agoThought experiment: imagine doing React development with all inline styles. Someone invents CSS. Would you use it? Of course not: CSS is a bad idea in 2019. In 2004 it solved some of the problems we have React to solve today, but much, much weaker
- consolenaut 8y agoAs someone coming from a traditional strict separation-of-content-and-style background and now convert to Styled Components, CSS-in-JS felt unnatural to me when I first encountered it. The problems with styles in large applications are well known and I had a solid handle on them with BEM and other bits of tooling, namespacing styles to a particular React component to avoid collisions etc. It took me helping my brother learn how to do web development to shake me out of that mindset. He's not from a traditional webdev background and he got quite far quite fast with React. When he showed me his code, I noticed he was inlining all of his styles in his relatively small React components. I was going to explain why its bad practice to do that, but when you're building small almost atomic components, that approach actually makes a lot of sense, its what the BEM methodology tries to do albeit in a poorer way. CSS-in-JS tools like Styled Components preserve the spirit of this approach and minimise the downsides. I think CSS-in-JS lends itself quite nicely to atomic design. At my current company, one of the first things we did was build a component library of atoms & molecules that are shared across many applications, keeping our design language very consistent. We also make heavy use of Styled Components' theming capabilities, so we wrap our React apps with a ThemeProvider and give it an object with theme variables that drive the look and feel of our components. This is super useful when you have to support whitelabeling like we do, but even if you don't, its nice to keep your mystery-meat colors and spacings all in one place similar to how you might with SASS. One of the gripes a lot of people have with CSS-in-JS is portability, and while that is a drawback, I feel it's an anti-pattern to rely on shared CSS styles to enforce design consistency across many deployables. It's kind of a classic case of developers trying to solve a process issue with technology, which is admirable, but from experience styles go out-of-sync with eachother quite easily and its rare that you can drop a CSS file into another project and have styles just work without having to do rework, so the benefits of sharing CSS rather than writing new styles off a styleguide are marginal at best. Again, this is all my subjective experience, your mileage may vary. We still have a couple of issues with Styled Components, no technology is perfect and SC is still relatively young, but so far the pros have far outweighed the cons to the point where none of us really feel the itch to go back to SASS or plain CSS. I'm definitively not a magpie developer by any stretch, I'm usually resistant to change for the sake of change, but CSS-in-JS makes a lot of sense when you use it how its intended
- headcanon 8y agostyled-components is not popular on HN it seems. Allow me to share my own positive experience: I have built websites in a variety of different ways, with a variety of different CSS schemes. I've worked with SASS, LESS, BEM, every major css framework, in both SPA and SSR environments. I have also built react SPAs with the above variety of CSS schemes, as well as CSS-in-JS libraries like Aphrodite and Styled Components. I currently build and maintain a medium-to-large web app with a small team, right now ~200 components, 31k lines of js including test files. Styled Components has been an immensely positive experience for us, and i would not want to use any other way I have mentioned, or has been mentioned in this thread, to manage our styles in our app. The reason why is because of the simple fact that it allows us to think of our styles just like any other component. We do not need a separate way of managing styles that we need to keep track of, whether a style is used is 100% the same as whether a component is used or not, which makes eliminating dead code, dead styles, easily managed through tooling. It allows us to define simple, semantically-named components like <FlexGrid/> and <BigButton/>, and allows us to compose these components together to build up styles just like any other react component. Styles are easily overridden from their parents. We use Ant Design for our UI toolkit, which does not use Styled Components, but any styles we want to override, as well as styles in nested classes, are easily done by wrapping an antd component. All the parent component needs to do is accept a "className" property. This makes interop with other components simple. Effectively what this means is that after awhile, we get to live in a world where I can add a component into any given part of application, and be very certain its going to look and behave the same way it does in every other part of the application. When I'm building new features I don't want to think about styles, except when adding styles is part of the feature itself. Styled Components is the only way so far I've found that does that sufficently. Globally-available CSS is great for web pages, but not so much for widget-based GUI web apps, which creates leaky abstractions. Most ways of managing CSS are systems to get around that, or treat it as a feature. In short, 10/10 would use again, even over other CSS-in-JS libraries like Aphrodite. Note this opinion is scoped purely to react apps. Vue's approach seems appealing as well but I have not used it before, but to be honest I do prefer being able to have everything in JS or JSX, but thats a different discussion.
- woah 8y agoI hated styled-components when I had to use it. It introduces a ton of unnecessary nesting and weird abstractions just to give devs something that is superficially similar to something they are familiar with. I keep it simple with styles in JS.
- LeonM 8y agoBe very aware that most popular CSS-in-JS libraries (such as JSS) will completely break CSP (Content Security Policy). The default reaction is usually "Just allow unsafe-inline in your CSP header", but this is dangerous advise as it will disable CSP! I've even seen 'experts' advising to use webpack to set a static value as a CSP nonce during build-time... If you want to use CSS-in-JS, you'll either have to use server-side rendering to inject CSP nonces in your index.htm [0], or set up a complex build system to extract the CSS from your JS so you can serve them as .css files. Using server-side rendering to inject nonces into your single-page client side rendered webpage is such an ugly hack. I'd prefer the second solution but I have not been able to find a solution like that, nor do I have the time to dive into the webpack rabbit-hole to do so. [0] https://github.com/cssinjs/jss/blob/master/docs/csp.md https://github.com/cssinjs/jss/blob/master/docs/csp.md
- antihero 8y agoWhy is it that whenever anyone posts anything about React, there's a horde of Vue users trying to convince us that they are doing it better? It feels a bit desperate. The great thing about React is it is purely JS (or JSX, which is effectively a macro for the underlying JS). Which means it is explicit, and predictable. Perhaps that means there's less sugar, but any sugar and magic comes at a price. I'm going to have a look at Vue more anyway, out of curiosity, though. Edit: I note that some of the anger at React has been "Why does it need Redux/MobX if it is so good?". But Vue has Vuex to solve the same problem?
- austincheney 8y agoStory of my life as a front end developer... you can invent an abstraction to make life easier and simultaneously increase code size and complexity more than 10 fold. Easy is often an anti-thesis of simple. Basic front end code isn't that challenging, but it does take some actual practice (not half-ass practice followed by a million poorly considered short-cuts).
- exogen 8y agoWhat about non-basic front end code?
- austincheney 8y agoWell I did spend this weekend trying figure out how to dynamically update keyframe rules with JavaScript only to discover the window.CSSKeyframesRule API is incomplete on most browsers so I found a different nonstandard way to solve that problem cross browser. I have not seen a failure to implement standards like that in many years. Just about everything else on the frontend is absolutely solid cross browser with 5+ years of thoroughly tested support. People don’t write abstractions to fix weak technology, they do it to fix weak developers.
- exogen 8y agoNo.
- latronic_notron 8y agoIn recent projects I tried 3 new approaches: React's CSS-in-JS, Vue's Scoped CSS and Tachyons/Tailwind Atomic CSS. All of those solutions were a huge improvement and scaled better than any of the previous pure-CSS techniques I was using before. BUT the key here is that those things only work when you rely on React/Vue/etc components. If you have have to rely on copy/pasting markup, things go wrong FAST and you lose track of your app style and things get duplicated. You also to have to enforce SMALL components. If you duplicate markup between components things get hard (but not as nasty as if you weren't using components). I honestly believe that people not using modern frameworks can't see the advantages of any of those techniques, and would urge everyone to try them out in component-based project.
- deltron3030 8y agoThose techniques work well for design systems. CSS in JS on its own, and Vue's Scoped CSS are a different thing than Tachyons, Tailwind or Styled System. Styled System is for CSS in JS what Tachyons is for CSS, you're using a design system, either the default values that are already present, or your own customizations. This basically frees you from making style decisions while coding, depending on your design system, things will just work well together as you create your components, with spacing, colors etc. all being already figured out. This means that you don't "translate" pixel perfect designs, you use design tools like Sketch or Figma to find the rules and scales that you then translate into the style sheet/design system. Instead of doing the "configuration" in your CSS when you're coding, you basically have an intermediate step where you set up those rules in advance, and can just focus on composition.
- latronic_notron 8y ago> Those techniques work well for design systems. That's true! I find that enforcing a consistent and quickly-changing design system is way easier than when I was using old techniques. > Instead of doing the "configuration" in your CSS when you're coding, you basically have an intermediate step where you set up those rules in advance, and can just focus on composition itself. You summed it up perfectly
- exogen 8y agoImagine a programming language that only had global variables. You have to carefully name your variables using complicated conventions in order to avoid any conflicts or unexpected behavior. Even your functions don't have local variables; there is no lexical scoping. Any function can overwrite or mutate what any other function is doing inside. There is no real encapsulation. After you've done this perfectly, your application gets bigger and you start wanting to reuse third-party modules made by other developers, because they've already solved some of your problems. Uh-oh: they didn't follow exactly the same conventions, and now things conflict. Or their variable names were perfectly unique in their own code base but not when combined with yours (or when combined with several other third-party modules). This language is CSS and is why people are so fed up with selectors. Even "scoped" selectors really aren't lexically scoped in the sense that other languages handle scoping... it's still just another naming convention hack. I use CSS-in-JS because CSS wasn't designed to be a language that survives attempts at modularization, third-party code sharing, etc. No sane programming language attempting this would only have global variables. So, we throw out the selectors part of CSS and keep the rest, at least for now. Nobody using CSS-in-JS thinks this is an ideal situation. Nobody wakes up thinking, "oh my god, I need to put my CSS in my JS, it would be perfect." We're just trying to deal with the hand that's been dealt.
- pmlnr 8y agoCSS is not a programming language, and it shouldn't be viewed or compared as one. It has different functionalities.
- exogen 8y agoIt's a language either way, whether you consider it "programming" is not really important. So, good luck with that. I live in the real world where it's used almost exclusively by programmers.
- gaastonsr 8y agoCSS is a tool used by web developers to style their websites. Whether technically it's a programming language or not is tangential.
- jasonhansel 8y agoI'm of the opinion that CSS actually has more in common with logic-based programming languages (like Prolog, or more specifically ones based on defeasible logic) than with ordinary languages of the "imperative" or "functional" sort. I think that reading CSS with this in mind helps make sense of some of CSS's features (e.g. specificity, the way selectors work).
- chiefalchemist 8y agoCSS === Cascading Style Sheets In the context describe in the article, there is nothing cascading, and there are no sheets. What he / she is doing is going back to the late 90's and inlining all the style'ing. I'm not judging the technique, simply pointing out that it's not actually CSS.
- weslly 8y agoWhat I don't like about css-in-js is how it makes things really hard (or even impossible) for endusers who may want to use an extension like stylus or tampermonkey to modify the site styling or behaviour.
- ringaroll 8y agoCSS was a mistake. Adding new features will not fix it. It needs to be scraped and rethought from scratch. There needs to be a something completely new to replace it, and it must be a full programming language.
- raphaelrk 8y agoI'm always surprised to find no mention of React Native in discussions around CSS in JavaScript. They've got it figured out. Stick your styles at the bottom of your component. Vertical flexbox by default. And... that's about it. It just works beyond that point. We liked it so much we ported our webapp from react to react-native-web. It's an amazing library. You can freely mix in regular react, but the styling story is so good with react-native-web that you'd never want to. It powers mobile.twitter.com and the author (same person who made normalize.css) recently joined Facebook, which hopefully means more development to come. You'd have to pay me to go back to styling the web with css. It really is a hair-pulling experience.
- cbdumas 8y agoI got to web development pretty late (circa 2015) so my perspective may be skewed but CSS in JS seems much more natural to me than separating markup from style and then linking them up later with global class names. It reminds me of when I was in college learning C where all of your code is just dumped into one namespace, and then later learning Python (or basically any other modern language) with actual modules and namespaces. After seeing it done that way it just makes no sense that it would ever be done the old way again.
- hitekker 8y ago"Deprecate CSS, disregard design" seems to be the standard practice for engineers silo'd off from designers, and the business-at-large.
- yellowapple 8y agoI feel like a lot of this boils down to a variation on Greenspun's Tenth Rule: "Any JavaScript-centric web development framework contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of a web browser." "I can add, change and delete CSS without any unexpected consequences. My changes to the styling of a component will not affect anything else. If I delete a component, I delete its CSS too." This is readily achievable with ordinary CSS. Selectors by ID/class have existed for multiple decades. A Ctrl-F for said ID/class name should be pretty painless to do even in the case where you're doing everything in one giant spreadsheet (though in this day and age of CSS preprocessors, no reason why you couldn't have widget.js and widget.css, the latter of which gets compiled into the final spreadsheet as part of the build process). "Never go on a hunt for CSS affecting your components ever again." I'd hardly call Ctrl-F a "hunt". JavaScript can't fix bad code hygiene/organization. "I cannot expect all team members, particularly juniors, to have an encyclopedic understanding of CSS." So you expect them to have an encyclopedic understanding of your CSS-in-JS library instead, then? Or perhaps it'd me more reasonable to be okay with looking things up every once in awhile? "With CSS-in-JS, we automatically sidestep common CSS frustrations such as class name collisions and specificity wars." I'm curious how much these are actually problems in the first place (or at least problems inherent in CSS itself), and how a CSS-in-JS framework expects to solve them without completely reinventing the browser's styling engine. "This leads to a marginally slower time to interactive, but a much quicker first meaningful paint!" If you didn't try to do everything with a giant blob of JS, you wouldn't have to do these kinds of ridiculous tricks to reduce time-to-first-paint. "Send only the critical CSS to the user for a rapid first paint." If the CSS is not critical, then it shouldn't be sent at all. No reason a backend framework couldn't selectively send only the CSS relevant to the HTML being sent. "Simply style your components with a global theme or based on different states." <foo class="widget primary"></foo> <foo class="widget secondary"></foo> So difficult. "CSS-in-JS combines all these benefits into one handy package and enforces them." Yes, at the cost of needlessly reinventing stylesheets and making it significantly more difficult to modify the styles downstream (e.g. for accessibility reasons). "Thousands of companies use CSS-in-JS in production [...] (including this website)" As an experiment, I switched JS off for that page and refreshed. The styling certainly doesn't seem to be happening client-side. Instead, the HTML source contains a bunch of obfuscatedly-classed divs and a giant obfuscated stylesheet in an inline <style> tag. Surely JS is not specifically needed to achieve this result. This could've been done with CSS-in-Python or CSS-in-Ruby or CSS-in-C or CSS-in-Lisp or CSS-in-COBOL or CSS-in-Brainfuck or whatever. It also could've surely been done with a dedicated language-agnostic CSS preprocessor. Further, it could've been done the "hard" way (not really hard at all) with CSS selectors alone (since that is indeed the end result).
- graphememes 8y agoWhy I don't write CSS in JavaScript: people disable it
- meehow 8y agoEvery time when some language generator become more popular, it's a sign, that something is wrong with the main language. It happened to Java, JavaScript, CSS.
- pvorb 8y agoI wonder what impact CSS-in-JS has on rendering performance and code size. I bet that browsers are very efficient at parsing and applying CSS directives to elements. Parsing and executing the JS and additional DOM manipulations could have a massive negative impact on performance, at least intuitively. Does anybody know of a performance benchmark that compares CSS-in-JS to regular CSS?
- JetSpiegel 8y agoWay to defeat the purpose of CSS. How is hard-coding the styles to each element something better? How can this not lead to MB of worthless crap to download, instead of the content? Want to show a title? Use `<h1>`, and style it with `h1 {color:palevioletred;font-size:18px;}`. Except hardcoding the font-size as pixels is another code smell, the `h1` is already bigger than the text body. Use `2em` if you really need things to stand out. It's in the name, Cascading.
- cleanyourroom 8y agoHi, I'm from the orthodoxy and I'm here to disparage you. $disparaging_paragraph Thank you
- hypertext7 8y agoThis stuff irritates me. Imagine if you read an article titled "why I listen to audio books". Nobody cares. Do whatever works for you.
- 8lall0 8y agoNothing in Javascript makes me not afraid, the less i have to touch it, the better i feel. SASS + BEM accomplish the result in a more manageable way.
- designingsean 8y agoSo reading this article made me have a bit of an epiphany: What is being described isn't CSS-in-JS. Instead, this is style properties in JS. This is the equivalent of inline styles. We don't call it "inline CSS" because it isn't CSS. Nothing cascades with inline styles, just as they don't with "CSS-in-JS". And you don't have to worry about specificity with either implementation. In other words - all the things that make CSS the powerful language it is are stripped away to just a listing of arbitrary properties. So, CSS-in-JS, do yourself a favor and stop calling it that, because what you are coding is nothing even remotely close to CSS.