Files
react-native-web/docs/style.md
Nicolas Gallagher abf2c0307f Rewrite documentation
2015-09-07 09:38:25 -07:00

3.7 KiB

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, react-free-style, react-inline, react-native, react-style, stilr.

Style syntax: native vs proprietary data structure

React Native for Web diverges from React Native by using plain JS objects for styles:

<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.

<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:

<Text style={styles.root}>...</Text>

const styles = {
  root: {
    background: 'transparent',
    display: 'flex',
    flexGrow: 1,
    justifyContent: 'center'
  }
};

Yields:

<span className="_abcde _fghij _klmno _pqrst">...</span>

And is backed by:

._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, Basscss, SUIT CSS, and tachyons 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:

<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).