Recently, Facebook (owned by Meta) released its own CSS-in-JS library called StyleX. According to the developers, it is great for large projects and its key advantage is performance. It is expected that StyleX will now be promoted as a best practice for React projects.
The claimed benefits of using StyleX are reuse, typification, and everything will be cool on large projects. Well, finally getting a complete “Single File Component” file with JS, CSS, and HTML in one bottle.
Key Benefits
The library developers declare several advantages:
- Performance – the library at the compilation stage using the Babel plugin turns JS into a single CSS file optimized for size, thus we avoid classic CSS-in-JS runtime problems.
- Scalability – the ingenious Babel plugin uses file-level caching and generates atomic class names, which minimizes the size of the bundle, and the increase in the number of components in the application does not greatly affect the size of the CSS file.
- Predictability – Selector prioritization in StyleX is very simple – the last style specified always wins. This means that you can forget about cascading.
- Combinability – style objects can be exported and passed into components. In this case, styles will always behave predictably.
- Typing – Every CSS property and variable is fully typed, and we can use TypeScript or Flow to define the styles passed to the component.
- Everything in one place – the library encourages defining styles in the same file as the component, one small file over many smaller files. With this approach, StyleX removes unused properties from the bundle and removes duplicates.
Among other features, we have:
- Deterministic resolution
- Low-cost abstractions
- Small API surface
- Type-Safe styles
- Shareable constants
- Framework-agnostic
- Encapsulation
- Readability & maintainability
- Modularity and composability
- Avoid global configuration
Here’s how Facebook justifies the reasons for creating StyleX:
The legacy Facebook site used something similar to CSS modules and suffered from various problems that inspired the creation of CSS-in-JS. The average visitor of facebook.com had to download tens of megabytes of CSS, most of which were not used. To optimize initial loading, we lazily loaded our CSS, which in turn resulted in slow refresh (or “Interaction to Next Paint”). The use of complex selectors led to conflicts or selectors’ “specificity wars”. Engineers often resorted to using
!important
or more complex selectors to solve their problems, making the entire system progressively worse.A few years ago, when we were rebuilding facebook.com from the ground up using React, we realized we needed something better and created StyleX.
StyleX was designed to scale and its design has proven its effectiveness over years of use. We’ve added new features to StyleX without sacrificing performance or scalability, making StyleX even more enjoyable to use.
Using StyleX has been a significant improvement for us at Meta, both in terms of scalability and expressiveness. At facebook.com, we were able to reduce the number of CSS packages from tens of megabytes of lazily loaded CSS to a single package that was a couple of hundred kilobytes in size. We created StyleX to not only meet the styling needs of React developers on the web but also to unify styling for React across the web and native.
StyleX is a framework agnostic. This means that the library can be used with any JS framework: React, Angular, you name it. However, for those that use custom file extensions, such as Svelte and Vue, it may require additional configuration.
Let’s take a look at an example of the use, and main features of this framework. The code looks as:
import {Button} from ". /Button" import * as stylex from "@stylexjs/stylex" const .styles = stylex.create({ heading: { color: "red", }, button: { margin: 20px, } }) export default function App() { return ( <> <h1 { ... stylex.props(styles.heading)}>Heading</h1> <Button styles={styles.button}>Button</Button> <> ) }
Compared to Tailwind, we have access to built-in types that allow us to clearly define properties that can be overridden. There’s no need to need to create a separate prop for each property.
Criticism
With a desire to eliminate selectors’ priority, StyleX takes developers away from the cascade nature of CSS, along with a large scope of its built-in features. It brings a feeling that a pair of HTML+CSS is considered to be complex for a mass developer, so instead we get JSX along with several CSS frameworks.
For simple sites, you don’t have to make things over-complex, and you can get well with pure HTML and CSS. Modern CSS is ****** enough and supports a responsive grid natively with a minor code, for those who need that.
When searching for a specific problem, you’ll find the solution recipe in pure CSS, not StyleX, because the CSS community is wider than the one for a just-released library. That means you have to “translate” it to StyleX to test with your code, and other ways around – when having issues with styles, you’ll need to translate it to raw CSS to ask somewhere like StackOverflow.
Finally, StyleX is another dependency for Webpack, which adds on.
Conclusion
Despite the criticism, I think this framework will be truly helpful on large projects when building complex design systems that are used by many teams. Facebook tested and refined its product for three years before releasing it to open source. It seems to me that this is a sufficient reason to believe that the library is tested and can be used in real projects.