Frank Yan discussed at React Conf some of the technologies and strategies powering FB5, the new facebook.com, addressing topics such as Facebook’s approach to CSS-in-JS.
Facebook’s website started as a simple PHP webpage. As richer and more interactive features such as messaging and live videos were added to the platform, the stack complexified to include a combination of CSS, vanilla JavaScript, Flux, React, and Relay, with a negative impact of page size and performance. To build the user experience they needed for their products, Facebook decided to rebuild from the ground up with the following requirements: modern design system with support for theming, improved accessibility, faster page loads, and seamless interactions. The new Facebook website is a single-page app with a React/GraphQL/Relay stack.
Given Facebook’s specific constraints, it decided to create its own CSS-in-JS library. The underlying idea was to not discard idiomatic CSS but to make it easier to maintain and keep the good parts of CSS that developers are used to enjoying. The number one priority was readability and maintainability, which are issues compounded at scale. Yan gave a code sample featuring Facebook’s CSS-in-JS version in action:
const styles = stylex.create({
blue: {color: 'blue'},
red: {color: 'red'}
});
function MyComponent(props) {
return (
<span className={styles('blue', 'red')}>
I'm blue
</span>
)
}
In the previous examples, CSS specificity issues which may lead to unpredictable styling are eliminated; the latest style to be applied (red) will be in place.
One of the first things designers asked for was the dark mode. To implement theming abilities, the Facebook team used CSS variables, also known as custom CSS properties. CSS variables propagate their values to the element’s subtree the same way that React Context does, which led to replacing use cases of Context for holding theme-related values with the use of a native browser feature. Instead of passing SVG files to img
tags, SVG icons were passed as React components, which allowed to customize the icon according to the theme. Icons thus may change color at runtime without requiring additional downloads.
Accessibility-wise, font sizes have been changed from a fixed pixel (px
) basis to a font-size-proportional rem
basis.
As styles are embedded in JavaScript files, JavaScript tooling can be used to perform checks whether static checks (like type checking style objects, or linting), or runtime checks. In Facebook’s development environment, if some elements appear at rumtime to be inaccessible or incompatible with dark mode, or slow to render, developers can visibly and functionally block them and are provided with actionable recommendations to solve the detected problems.
From the style rules provided in JavaScript files, atomic CSS files are generated, in which each class refers to a CSS property/value pair. For instance, the previous code example may lead to the following CSS declarations:
.c0 { color: blue}
.c1 { color: red}
Those CSS declarations can then be reused anywhere the developers is using a blue or red color. The reuse combined to the short names reduces the size of the generated stylesheet but also breaks the linear growth pattern that was observed between CSS file size and features. Yan mentioned that CSS file size has been reduced from 413 KB to 73 KB, while still including the dark mode implementation.
Further optimizations may apply. Yan showed how a stylex
style declaration disappears as constant CSS properties are replaced in the component code by their values, thus eliminating a large fraction of the runtime cost of using the CSS-in-JS library, while maintaining compatibility with server-side rendering.
The described CSS-in-JS approach is reminiscent of the library Atomic CSS, which relies on single-purpose styling units, the no-runtime CSS-in-JS library Linaria, and Facebook’s Prepack, a JavaScript bundle optimizer.
Yan’s full talk is available on ReactConf’s site and contains further code snippets and detailed explanations. React Conf is the official Facebook React event. React Conf was held in 2019 in Henderson, Nevada, on October 24 & 25.