StyleX – Meta's styling library
stylexjs.comThis is probably a better place to start: https://stylexjs.com/blog/introducing-stylex/
> We created StyleX not only to meet the styling needs of React developers on the web, but to unify styling for React across web and native.
Meta friends, the names "Review" and "Restyle" were right there.
> StyleX is a CSS-in-JS solution, not a CSS-in-React solution. Although StyleX been tailored to works best with React today, It's designed to be used with any JavaScript framework that allows authoring markup in Javacript. This includes frameworks that use JSX, template strings, etc.
https://stylexjs.com/docs/learn/thinking-in-stylex/#framewor...
I wouldn't be surprised if they avoided starting with "re" on purpose to avoid it seeming like this was a react only framework.
Shopify has a styling library for React Native called Restyle: https://github.com/Shopify/restyle
I like it a lot. It lets you define a theme with design tokens like spacing and colors, then enforces using only those via TypeScript (with an escape hatch via style prop), which also gives you editor autosuggest support without hacks like the Tailwind extension.
I really enjoy when libraries or languages have a “Thinking in X” post of some kind. I find it really helps orient me once I actually get to writing some code. If anybody has any “Thinking in X” examples that you have found particularly useful, let me know!
It was React Conf 2018 in Nevada when they first talked about StyleX and said they planned to open source it. Though I thought it was going to come much sooner than 5 years, I am so glad it has been released! 2018 was peak css-in-js era and StyleX approach of deduping classes and remove runtime JS was a really performant approach and it sounded like the DX was nice as well.
Just at a cursory glance, this looks pretty verbose and clunky. Existing React ecosystem styling solutions are many, so it’s not immediately evident to me when you would accept the trade offs introduced by this tool over any existing ones that seem much nicer to not only integrate, but also have to work with day to day.
0 runtime is the argument over emotion (and therefore MUI right now)
You'll be glad to hear that MUI is zeroing in (pun intended) on a zero runtime solution right now as an alternative to Emotion [0], although that GitHub issue doesn't capture just how far it has come. Expect more soon!
they are not the same kind of thing though, one is a library TO WORK WITH styles, the other is a library AND some styles
thanks for pointing this out. I hope they extend their `thinking in stylex` page with this info.
They do, albeit it's a bit confusing
https://stylexjs.com/docs/learn/thinking-in-stylex/
> There is no runtime overhead here
Specifically
> No runtime style injection.
There's still a runtime though
> Optimized runtime for merging class names.
They explain the 0-runtime pretty thoroughly.
it was exciting at launch, but took forever to ship, and now Tailwind has run away with that problem.
Announced at React Conf 2018, I was so hyped for it back then! I did not expect it to take 5 years.
We should keep this in mind and adapt our expectations about forget, the compiler that they announced like one year ago
already forgotten
Agreed! It’s been used internally at Meta for so long, but I don’t miss it after adopting Tailwind.
This looks interesting and I'll play around with it. It will be tough to replace CSS modules and plain CSS for my React apps though. CSS is so much better now. Did you know you can nest in CSS natively now? https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting
You can, but your CSS won't work properly for nearly 20% of users
I hate having to give everything a name like people do in react native stylesheets. Give me an inline performant style prop any day
Hey! I'm the maintainer of StyleX and I just wanted to say that you would probably like PandaCSS or Tamagui.
We don't think the Tailwind way of styling is readable in the long term, but we see the value is being able to author that way. We're looking into a VS Code plugin, that would let you author your styles inline and extract them out when you save.
Fair enough, that would be a good start. I just see such a smooth workflow in being able to do styles for elements with only a few custom styles inline.
I mentioned below, I do this with mui sx right now when <= 4 styles
E.g. sx={{ alignSelf: 'flex-end' }}
I think the reason it works so well is the same reason people love tailwind (it's all in one place), so the plugin would be helpful but still take away from that workflow when it comes to reading and maintaining.
You already have to name your CSS classes, and atomic CSS libraries are chock full of names you must learn.
What do you mean "inline style prop," writing CSS in the HTML style attribute? That's a nightmare to manage across large apps, not composable or reusable, and this library compiles to performant styling (according to the authors/examples).
To anyone for which learning lots of names of things that you use semi-frequently is a bottleneck: you can use spaced repetition (https://en.wikipedia.org/wiki/Spaced_repetition) to remember them way more easily. I use Anki (https://apps.ankiweb.net/), SuperMemo is another option (with other features, and lots of interesting articles on their website).
For example, I've been using it to remember shell commands and options. Now whenever I have to search for an option that I think will be useful in the future, for example `-M/--max-columns` for ripgrep, I put it in Anki (question: "Ripgrep: Search for 'clukay' and don't print columns longer than 200 bytes", answer: "rg -M/--max-columns 200 clukay"). Each day I review my cards (~5/10 minutes at most). I used to not be able to remember an option like that that I use once a week, but now I can.
For more info on how to use it effectively, I've found https://borretti.me/article/effective-spaced-repetition to be really helpful.
Nitpick, but most atomic css libraries name things fairly consistently. In addition, you only have to memorize the names once. After that learning curve, you never have to think of a class name again.
In addition, with robust IDE support, you can type the css attribute and get autocomplete suggestions for the relevant utility.
So we're told every time. Is it "2xl" or "xxl" for the breakpoint again? It depends on the library (hopefully you didn't customize it!). Was it Tachyons or Bulma that has "ns" for "not small?"
> you only have to memorize the names once
Yep! After that it's as simple as dark:hover:md:motion-reduce:text-base/7
> you never have to think of a class name again
Unless you're using Tailwind's custom themes, arbitrary groups, peers...
e.g. using mui sx. the downside is the runtime performance cost
https://mui.com/system/getting-started/usage/#performance-tr...
i don't want to reuse or compose my styles, i just want to add alignSelf: 'flex-end' and then easily be able to change it and see the styles in one place, without leaving the component definition. the reusability and composition is at the component level
Thanks! Great reason this beats MUI.
Not trying to hate on atomic CSS, composable classes and style tokens are good. Even one of the devs on this project commented on them here:
> We don't think the Tailwind way of styling is readable in the long term, but we see the value is being able to author that way
https://news.ycombinator.com/item?id=38540629
The docs here mention the downsides though.
> Great reason this beats MUI.
Not at all, mui gives you the option to do either.
I don't want my style library being opinionated about my coding style.
Ohh I see, I honestly didn't click the first time. You meant sx in MUI, not StyleX. We're gonna need more names.
Inline styles by themselves don't support a lot of necessary CSS things like media and child selectors. You lose the "cascading" part of CSS...
Try out Tamagui which solves this - child and media selectors, even container queries and stuff like container + pseudo.
Unclear if they mean inline styles as in "the HTML attribute" or a React prop. Tamagui doesn't solve the former.
Part of me was holding out hope that React and it’s surrounding ecosystem might at some point end up back on a path that is somewhat more aligned with the rest of the web and had some meaningful sense of interoperability with everything that’s not React.
This certainly inspired no confidence in that.
All I will say is that CSS has gotten a LOT better in the past 5 years and for almost every scenario I can think of you would be in such a better position if you just spent a month learning that rather than this new abstraction.
Could you share some resources that you have found useful to renew basic CSS knowledge?
This and the rest of his content were very useful resources imo.
https://www.joshwcomeau.com/css/interactive-guide-to-flexbox...
I think Flexbox specifically is around about the time a lot of people last looked at CSS and it’s actually everything after that that I was referring to.
I think this resource is pretty well put together from the Chrome dev rel folks https://web.dev/learn/css it obviously goes from 0 so you can pick and choose what parts make sense for you but based on both my own experience and after having talked to many others in the same scenario, if you feel like you never really “got” CSS with any sense of confidence I’d say start at maybe reviewing the box model and going on from there precisely because so much has changed all over the place since then.
How we think about layout is totally different, how we think about positioning is different, how we measure things is new, even things like colour have totally changed in big ways.
But more concretely I think a lot of the reasons that people had particularly bad experiences with CSS in the past that drove them towards things like this or Tailwind for example are now solved problems and that both this and Tailwind are kind of obsolete in many senses.
Keep in mind that this system while it was released publicly today is actually rather old technology and was built around solving a problem in a very specific way that makes a lot less sense now because it was solving problems that now have native CSS solutions with great cross browser support.
Nice! We copied StyleX's "type-safe extensions" in Truss [1] so things like `<MyButton xss={Css.mt5.$} />` are allowed (setting margin is fine) while disallowing `<MyButton xss={Css.dg.$} />` (anything "not margin") that would mess up the components internal impl details with a compile error.
That said, we don't actually use the feature that much, vs. higher-level logical props like `<MyButton compact />`.
I know we're supposed to use build-time CSS-in-JS these days, but afaiu they don't support the rare-but-handy "just spread together ~4-5 different object literals from ~random different conditionals + props", i.e. intermixing styles some inside the component + outside the component, which emotion handles really well.
Basically this [2]. StyleX says it does "cross-file styles"...but can it support that? I kinda assume not, but I'm not sure.
[1]: https://github.com/homebound-team/truss#xstyles--xss-extensi...
[2]: https://github.com/homebound-team/beam/blob/main/src/compone...
StyleX is compiler-time only, so yes misses out on dynamic styles.
I made Tamagui a hybrid of compile and runtime, where the optimizing compiler actually handles object spreads, conditional logic, and even cross-module imports. It's really nice to get the near-0-runtime performance while maintaining all the benefits of dynamic styles.
Hey! We support dynamic styles, too.
We're continuing to work on optimisations for StyleX, and I'll be looking at Tamagui for inspiration!
I got the impression it was not dynamic values? Just that you can combine static objects dynamically. If I’m wrong I’ll re read the docs but someone else pointed that out to me and linked part of the docs that seemed to indicate that.
It does support dynamic values.
Can you link me to how you know that? The docs seem to indicate it doesn't:
"Since StyleX depends on ahead-of-time compilation, it is important for all your styles to be statically analyzable"
"No runtime style injection."
"All styles are bundled in a static CSS file at compile-time."
---
By dynamic styles I assume we're talking about something like this:
{ backgroundColor: props.thirdPartyColor ?? randomColor() }
Cool, thanks Naman. It’s really great work overall, congrats on the launch. Maybe those couple places could have wording that indicates it supports dynamic as well.
StyleX supports this pattern. You can export a bunch of styles in one file and then import and use them in another.
You can import many different styles and apply them conditionally etc.
Also, completely dynamic styles are supported. We were inspired by Linaria's solution to generate CSS vars and set their value with inline styles.
Their introduction page[0] makes this look like material ui's makeStyles[1] approach?
[0] https://stylexjs.com/docs/learn/ [1] https://mui.com/system/styles/basics/
Yup, but without the handy `classes` prop so people can modify styles.
Plus, I find with v5, I never touch `makeStyles` / `styled`, the utility props / sx are enough.
It always surprises me the lengths people are willing to go to avoid writing CSS. If organization is the issue, there's BEM (https://getbem.com/). This just looks like another layer of complexity on top of an already convoluted front-end stack that just slows everything it touches to a crawl and only works moderately well on the developers beefed up latest MacBook Pro's, and sucks horribly on any regular person's computer.
The post mentions BEM specifically and argues why this alternative is better
> just slows everything it touches to a crawl
The docs call out how there's little to no overhead with the runtime.
Is any part of your comment related to this library specifically? Or just CSS-in-JS?
waited a long time for this since they first demoed it at react conf 2018? in vegas. this was the last piece in the SSR + streaming + suspense holy grail. looks like the pieces are all finally done. congrats on the launch
Borrows a lot from emotion/styled-components it appears. The extensive typing seems to be the biggest feature.
They mention why I should choose it over BEM or Tailwind, why choose it over MUI though?
Does anyone really like Material UI? I find it so clunky and heavy.
I for one don’t. I appreciate the incredible amount of effort the developers put into it, but I really dislike the basic affordances as prescribed by Material Design and end up customizing it a lot… and it clearly show its limits the
Fair point, I like the component library, and it's clunky but powerful.
createTheme() (from this library) seems clunky too, but makes sense.
Excited to explore just for the sake of alleviating “styling at a distance” pains
How does this compare to https://griffel.js.org/ ?
Great question, this strikes me as very similar.
This appears to place more emphasis on static typing, and has less strange syntax (think of "shorthand" in Griffel).
The docs steer you away from atomic CSS, whereas Griffel's embraces them.
Griffel and StyleX arrived at very similar ideas and we've discussed the possibility of sharing more code between the two.
There are some meaningful differences in the API choices, but the high-level design is pretty much the same.
React is one of these things that was designed to be unbeareable tonuse without custom syntax, but at least it is possible. This looks looks like it does not work without custom syntax at all. Type safety is a nice to have, but it should not need an exotic compiler plugin.
It needs a plugin, but I see no custom syntax, it’s just JS?
Always impressed by how insanely overcomplicated people can make CSS.
What scale of frontend apps do you work with? Specifically, how many developers are simultaneously writing features and merging code in a given week?
I'm assuming your question is loaded in an attempt to say "You haven't worked on any large teams then"
But I have, in a fairy large project (completely rebuilding all of Deere & Co's internal systems, upgrading from literal terminals to web app) with >100 developers merging in hundreds of PR's a week.
We've never needed something like this.
Do you work on deere.com? I haven't seen a conditional comment in a while!
> <!--[if lt IE 7]>
I think that site could benefit from something like this. The CSS on that site is, um, not optimized.
No, I worked on internal facing stuff that was only accessible by dealers
Sounds like simple crud apps that barely need styling and can use existing component libraries.
Ah yes, a 5 year, hundreds of engineers, multi-million dollar project to take 1980's terminal computer ordering system for millions of Deere dealerships and bring it to the modern ages through a web app is just a simple crud app that barely needs styling.
Do you ever just re-read your replies and think "I'm being ridiculous" and decide NOT to post it? You should do that more often.
Any examples specific to this post?
What's the advantage of css in js as opposed to just plain css?
- Styles colocated with markup/logic (I consider this an advantage with a component library like React, others may not)
- No global styles stomping on each other, styles scoped to a single module unless explicitly exported/imported
- Type safety, if using TypeScript
The main downside is often performance, though
We're solving the performance pitfall of CSS-in-JS libraries by making a compiler instead. In the vast majority of cases, there should be zero runtime cost to using StyleX.
Refactoring and knowing where styles are used. In css sometimes the btn class does something and sometimes not. With stylex it is explicit.
Styling based on js, eg striking through if an item becomes deleted, etc
Absolutely fuck all.
I couldn’t see pseudo selector (like :hover) support in the docs.
Another new library (I haven’t used yet) that supports pseudo selectors is called CSS Hooks: https://css-hooks.com/
CSS in JS is really a great concept to keep component logic colocated.
Although I’m really in love with @emotion/css where I can still write and copy paste css-snippets instead of translating into js object syntax.
It looks like the React-ification of CSS. No thanks!
To me it seems more like the typescript-ification of CSS which is a good thing if you’re into static types!
I don't see anything here that's React-only. They specify that it's not.