Skip to content

Commit

Permalink
first version of CSSOM RFC
Browse files Browse the repository at this point in the history
  • Loading branch information
kof committed Apr 20, 2020
1 parent 6db1582 commit 382d2d1
Showing 1 changed file with 102 additions and 0 deletions.
102 changes: 102 additions & 0 deletions text/0000-cssom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
- Start Date: 2020-04-20
- RFC PR:
- React Issue:

# Summary

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.

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.

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.

## Motivation

### Goals

- High-performance static styles via CSSOM. Rendering CSS only once and reusing across components and updates allows avoiding additional work within components render cycle.
- Lists - inline styles have no way to be reused across list elements, where typically styles are repeated.
- 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.
- Adhere to React's component model and the upcoming Suspense architecture.

### Non-goals

- Enforcing CSS-in-JS over vanilla CSS or css-modules (you can still use className)
- Replacing every possible interface/idea CSS-in-JS libs came up with

# Detailed design

### Tagged templates

- familiar syntax
- syntax highlighting
- linting
- ability to return a data structure that react can identify, not just a string
- interpolations

```js
import { css } from "react-cssom";
const buttonStyle = css`
color: red;
`; // {css: 'color: red;'}

render(<button style={buttonStyle}>x</button>);
```

### Using style prop for both inline and CSSOM styles

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.

Using the `style` prop allows us to be flexible in the future about how React wants to optimize and treat this interface.

That being said using a new prop like `css` is also an option:

```js
render(<button css={buttonStyle}>x</button>);
```

### Babel plugin

Babel plugin can be optional and can enable advanced features like:

- vendor prefixing
- optimizations
- other preprocessing options e.g. using PostCSS

After babel plugin the call into `css` tag function can be removed and the result of the above example can be compiled to:

```js
const buttonStyle = { css: `color: red;` };
render(<button style={buttonStyle}>x</button>);
```

# Drawbacks

- we are adding a new area of responsibility to React, which will require more work to maintain it, but hopefully can be parallelized
- it inevitably will raise the discussions about how React is enforcing CSS-in-JS, so we will have to prepare a good answer
- there are a number of unresolved features listed below, which will have to be addressed over time

# Alternatives

This is a very simple initial version, so it's not as feature-reach as some other CSS-in-JS solutions, but it has a potential to cover more use cases later.

It is not a replacement for react-native approach.

It is not a replacement for any entirely different approaches like SwiftUI.

# Adoption strategy

It is not a breaking change.

# How we teach this

It is a primitive interface for passing CSS to React in order to integrate with Component lifecylce. It can be also a way for babel plugins and compile-time procesing of CSS for React components.

# Unresolved questions

- Composition
- Overrides
- Dynamic or state-based styling
- Theming
- Alternative object-based syntax
- Compatibility with react-native

0 comments on commit 382d2d1

Please sign in to comment.