mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-23 23:06:24 +00:00
[add] StyleSheet API
Initial StyleSheet implementation for Web. Converts style object declarations to "atomic" CSS rules. Close gh-25
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
# StyleSheet
|
||||
|
||||
React Native for Web will automatically vendor-prefix styles applied to the
|
||||
libraries components. The `StyleSheet` abstraction converts predefined styles
|
||||
to CSS without a compile-time step. Some styles cannot be resolved outside of
|
||||
the render loop and are applied as inline styles.
|
||||
|
||||
The `style`-to-`className` conversion strategy is optimized to minimize the
|
||||
amount of CSS required. Unique declarations are defined using "atomic" CSS – a
|
||||
unique class name for a unique declaration.
|
||||
|
||||
React Native for Web includes a CSS reset to remove unwanted user agent styles
|
||||
from elements and pseudo-elements beyond the reach of React (e.g., `html` and
|
||||
`body`).
|
||||
|
||||
Create a new StyleSheet:
|
||||
|
||||
```
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
borderRadius: 4,
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#d6d7da',
|
||||
},
|
||||
title: {
|
||||
fontSize: 19,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
activeTitle: {
|
||||
color: 'red',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Use styles:
|
||||
|
||||
```js
|
||||
<View style={styles.container}>
|
||||
<Text
|
||||
style={{
|
||||
...styles.title,
|
||||
...(this.props.isActive && styles.activeTitle)
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
```
|
||||
|
||||
Render styles on the server or in the browser:
|
||||
|
||||
```js
|
||||
StyleSheet.renderToString()
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
**create**(obj: {[key: string]: any})
|
||||
|
||||
**renderToString**()
|
||||
|
||||
## Strategy
|
||||
|
||||
Mapping entire `style` objects to CSS rules can lead to increasingly large CSS
|
||||
files. Each new component adds new rules to the stylesheet.
|
||||
|
||||

|
||||
|
||||
React Native for Web uses an alternative strategy: mapping declarations to
|
||||
declarations.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
<View style={styles.root}>...</View>
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
background: 'transparent',
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Yields (in development):
|
||||
|
||||
```html
|
||||
<div className="background:transparent display:flex flexGrow:1 justifyContent:center">...</div>
|
||||
```
|
||||
|
||||
And is backed by the following CSS:
|
||||
|
||||
```css
|
||||
.background\:transparent {background:transparent;}
|
||||
.display\:flex {display:flex;}
|
||||
.flexGrow\:1 {flex-grow:1;}
|
||||
.justifyContext\:center {justify-content:center;}
|
||||
```
|
||||
|
||||
In production the class names are obfuscated.
|
||||
|
||||
(CSS libraries like [Atomic CSS](http://acss.io/),
|
||||
[Basscss](http://www.basscss.com/), [SUIT CSS](https://suitcss.github.io/), and
|
||||
[tachyons](http://tachyons.io/) are attempts to limit style scope and limit
|
||||
stylesheet growth in a similar way. But they're CSS utility libraries, each with a
|
||||
particular set of classes and features to learn. All of them require developers
|
||||
to manually connect CSS classes for given styles.)
|
||||
|
||||
## Media Queries, pseudo-classes, and pseudo-elements
|
||||
|
||||
Media Queries in JavaScript can be used to modify the render tree and styles.
|
||||
This has the benefit of co-locating breakpoint-specific DOM and style changes.
|
||||
|
||||
Pseudo-classes like `:hover` and `:focus` can be replaced with JavaScript
|
||||
events.
|
||||
|
||||
Pseudo-elements are not supported.
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
# Styling strategy
|
||||
|
||||
Using the `style` attribute would normally produce inline styles. There are
|
||||
several existing approaches to using the `style` attribute, some of which
|
||||
convert inline styles to static CSS:
|
||||
[jsxstyle](https://github.com/petehunt/jsxstyle),
|
||||
[react-free-style](https://github.com/blakeembrey/react-free-style/),
|
||||
[react-inline](https://github.com/martinandert/react-inline),
|
||||
[react-native](https://facebook.github.io/react-native/),
|
||||
[react-style](https://github.com/js-next/react-style),
|
||||
[stilr](https://github.com/kodyl/stilr).
|
||||
|
||||
## Style syntax: native vs proprietary data structure
|
||||
|
||||
React Native for Web diverges from React Native by using plain JS objects for
|
||||
styles:
|
||||
|
||||
```js
|
||||
<Text style={styles.root}>...</Text>
|
||||
|
||||
const styles = {
|
||||
root: {
|
||||
background: 'transparent',
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center'
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Most approaches to managing style in React introduce a proprietary data
|
||||
structure, often via an implementation of `Stylesheet.create`.
|
||||
|
||||
```js
|
||||
<Text style={styles.root}>...</Text>
|
||||
|
||||
const styles = Stylesheet.create({
|
||||
root: {
|
||||
background: 'transparent',
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## JS-to-CSS: conversion strategies
|
||||
|
||||
Mapping entire `style` objects to CSS rules can lead to increasingly large CSS
|
||||
files. Each new component adds new rules to the stylesheet.
|
||||
|
||||

|
||||
|
||||
One strategy for converting styles from JS to CSS is to map style objects to
|
||||
CSS rules. Another strategy is to map declarations to declarations.
|
||||
|
||||
React Native for Web currently includes a proof-of-concept implementation of
|
||||
the latter strategy. This results in smaller CSS files because all applications
|
||||
has fewer unique declarations than total declarations. Creating a new component
|
||||
with no new unique declarations results in no change to the CSS file.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
<Text style={styles.root}>...</Text>
|
||||
|
||||
const styles = {
|
||||
root: {
|
||||
background: 'transparent',
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center'
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Yields:
|
||||
|
||||
```html
|
||||
<span className="_abcde _fghij _klmno _pqrst">...</span>
|
||||
```
|
||||
|
||||
And is backed by:
|
||||
|
||||
```css
|
||||
._abcde { background: transparent }
|
||||
._fghij { display: flex }
|
||||
._klmno { flex-grow: 1 }
|
||||
._pqrst { justify-content: center }
|
||||
```
|
||||
|
||||
The current implementation uses a precomputed CSS library of single-declaration
|
||||
rules, with obfuscated selectors. This handles a signficant portion of possible
|
||||
declarations. A build-time implementation would produce more accurate CSS
|
||||
files and fall through to inline styles significantly less often.
|
||||
|
||||
(CSS libraries like [Atomic CSS](http://acss.io/),
|
||||
[Basscss](http://www.basscss.com/), [SUIT CSS](https://suitcss.github.io/), and
|
||||
[tachyons](http://tachyons.io/) are attempts to limit style scope and limit
|
||||
stylesheet growth in a similar way. But they're CSS utility libraries, each with a
|
||||
particular set of classes and features to learn. All of them require developers
|
||||
to manually connect CSS classes for given styles.)
|
||||
|
||||
## Dynamic styles: use inline styles
|
||||
|
||||
Some styles cannot be resolved ahead of time and continue to rely on inline
|
||||
styles:
|
||||
|
||||
```js
|
||||
<View style={{ backgroundColor: (Math.random() > 0.5 ? 'red' : 'black') }}>...</Text>
|
||||
```
|
||||
|
||||
## Media Queries, pseudo-classes, and pseudo-elements
|
||||
|
||||
Media Queries could be replaced with `mediaMatch`. This would have the added
|
||||
benefit of co-locating breakpoint-specific DOM and style changes. Perhaps Media
|
||||
Query data could be accessed on `this.content`?
|
||||
|
||||
Pseudo-classes like `:hover` and `:focus` can be handled with JavaScript.
|
||||
|
||||
Pseudo-elements should be avoided in general, but for particular cases like
|
||||
`::placeholder` it might be necessary to reimplement it in the `TextInput`
|
||||
component (see React Native's API).
|
||||
Reference in New Issue
Block a user