|
| 1 | +- Start Date: 2020-04-20 |
| 2 | +- RFC PR: |
| 3 | +- React Issue: |
| 4 | + |
| 5 | +# Summary |
| 6 | + |
| 7 | +I know it's a long-lasting and controversial topic and probably not the highest priority for the team right now, but let me try to create the first **simplified** vision for a CSS implementation we all could agree on. |
| 8 | + |
| 9 | +CSS-in-JS like React is on a dual mission, supporting both complex apps and small(ish) sites. This has created a big divide in the community because of the very different needs that these types of projects have. Like React, CSS-in-JS was born out of the need to reduce the complexity of maintaining large applications. |
| 10 | + |
| 11 | +While there are many options for authoring CSS, it is super tiresome to convince a team to use a particular approach. It creates a big divide and lots of frustration. While there is a huge value in not having a built-in solution and giving the space to 3rd party libs to thrive and experiment, the friction and frustration for not having a good built-in approach that covers 90% of use cases is real. |
| 12 | + |
| 13 | +## Motivation |
| 14 | + |
| 15 | +### Goals |
| 16 | + |
| 17 | +- High-performance rendering of static styles via CSSOM. |
| 18 | +- CSS Rules can be reused across components. |
| 19 | +- Components have no additional overhead for styling. |
| 20 | +- Lists - inline styles have no way to be reused across list elements, where typically styles are repeated. |
| 21 | +- Support the full CSS spec. Inline styles are limited to [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration) and we need to support the full spec on the web. |
| 22 | +- Adhere to React's component model and the upcoming Suspense architecture. |
| 23 | + |
| 24 | +### Non-goals |
| 25 | + |
| 26 | +- Enforcing CSS-in-JS over vanilla CSS or css-modules (you can still use className) |
| 27 | +- Implementing every possible idea CSS-in-JS libs came up with |
| 28 | + |
| 29 | +# Detailed design |
| 30 | + |
| 31 | +### Tagged templates |
| 32 | + |
| 33 | +- familiar syntax |
| 34 | +- syntax highlighting (already supported) |
| 35 | +- linting |
| 36 | +- ability to return a data structure that React can identify, not just a string |
| 37 | +- interpolations |
| 38 | + |
| 39 | +```js |
| 40 | +import { css } from "react-cssom"; |
| 41 | +const buttonStyle = css` |
| 42 | + color: red; |
| 43 | +`; // {css: '.css-0 { color: red; }'} |
| 44 | + |
| 45 | +render(<button style={buttonStyle}>x</button>); |
| 46 | +``` |
| 47 | + |
| 48 | +### Using style prop for both inline and CSSOM styles |
| 49 | + |
| 50 | +Since we can return from the tag function any data structure we want, we can identify styles created using our `css` function and we have no problem accepting both types of styles. |
| 51 | + |
| 52 | +Using the `style` prop allows us to be flexible in the future about how React wants to optimize and treat this interface. |
| 53 | + |
| 54 | +That being said using a new prop like `css` is also an option: |
| 55 | + |
| 56 | +```js |
| 57 | +render(<button css={buttonStyle}>x</button>); |
| 58 | +``` |
| 59 | + |
| 60 | +### Babel plugin |
| 61 | + |
| 62 | +Babel plugin can be optional and can enable advanced features like: |
| 63 | + |
| 64 | +- vendor prefixing |
| 65 | +- optimizations |
| 66 | +- other preprocessing options e.g. using PostCSS |
| 67 | + |
| 68 | +After babel plugin the call into `css` tag function can be removed and the result of the above example can be compiled to: |
| 69 | + |
| 70 | +```js |
| 71 | +const buttonStyle = { css: ".css-0 { color: red; }" }; |
| 72 | +render(<button style={buttonStyle}>x</button>); |
| 73 | +``` |
| 74 | + |
| 75 | +# Drawbacks |
| 76 | + |
| 77 | +- we are adding a new area of responsibility to React, which will require more work to maintain it, but hopefully can be parallelized |
| 78 | +- it inevitably will raise the discussions about how React is enforcing CSS-in-JS, so we will have to prepare a good answer |
| 79 | +- there are several of unresolved features listed below, which will have to be addressed over time |
| 80 | + |
| 81 | +# Alternatives |
| 82 | + |
| 83 | +This is a very simple initial version, so it's not as feature-rich as some other CSS-in-JS solutions, but it has a potential to cover more use cases later. |
| 84 | + |
| 85 | +It is not a replacement for react-native approach. |
| 86 | + |
| 87 | +It is not a replacement for any entirely different approaches like SwiftUI. |
| 88 | + |
| 89 | +# Adoption strategy |
| 90 | + |
| 91 | +It is not a breaking change. |
| 92 | + |
| 93 | +# How we teach this |
| 94 | + |
| 95 | +It is a primitive interface for passing CSS to React to integrate with component's lifecycle. It can be also a way for babel plugins and compile-time processing of CSS for React components. |
| 96 | + |
| 97 | +# Unresolved questions |
| 98 | + |
| 99 | +- Unique class names generation algorithm |
| 100 | +- Composition |
| 101 | +- Overrides |
| 102 | +- Dynamic or state-based styling |
| 103 | +- Theming |
| 104 | +- Alternative object-based syntax |
| 105 | +- Compatibility with react-native |
0 commit comments