Styling components
React Strict DOM includes a simple, scalable, and deterministic styling system. It produces optimized CSS output on web and adds many declarative styling features to native.
Creating styles
Styles are created with the css.create
function and a map of style objects. In the example below, there are 2 named style rules - one called "base" and the other "highlighted". The names are arbitrary and represent the constant used to capture the result of the function call.
import { css } from 'react-strict-dom';
const styles = css.create({
base: {
fontSize: 16,
lineHeight: 1.5,
color: 'rgb(60,60,60)',
},
highlighted: {
color: 'rebeccapurple',
},
});
Although styles can be inherited, there is no "selector" API and therefore no "styling at a distance".
Shortform properties
Shortform properties style multiple properties at once. For example, margin
sets the value for the left, right, top, and bottom margins on an element. React Strict DOM only allows a single value to be used with a shortform property, i.e., margin: "1rem"
is allowed but margin: "1rem 2rem"
is not. A shortform property can only be used to set the same value for each of the longform properties that it represents.
Pseudo-elements
Pseudo-elements are a way of targeting shadow elements contained within the native elements provided by React Strict DOM. Currently, the only supported pseudo-element is ::placeholder
, which references the element that contains placeholder text within an html.input
or html.textarea
element. Only the color
style can be set on a placeholder.
import { css } from 'react-strict-dom';
const styles = css.create({
input: {
'::placeholder': {
color: '#999',
}
},
});
Pseudo-states
Pseudo-classes represent different states of an element. Declarations for pseudo-classes must be nested within properties. For example, to change the background color for different states:
import { css } from 'react-strict-dom';
const styles = css.create({
button: {
backgroundColor: {
default: 'lightblue',
':hover': 'blue',
':active': 'darkblue',
},
},
});
The default
case is required when specifying property states. If you don't want any style to be applied in the default case, use null
as the value.
Media queries
Different media states of an element must also be nested within a property. The key should be a valid Media Query. For example:
import { css } from 'react-strict-dom';
const styles = css.create({
base: {
width: {
default: 800,
'@media (max-width: 800px)': '100%',
'@media (min-width: 1540px)': 1366,
},
},
});
Fallback styles
The firstThatWorks
method can be used to define fallback values that should be used in cases where a platform (or browser) might not support the first value.
import { css } from 'react-strict-dom';
const styles = css.create({
header: {
position: css.firstThatWorks('sticky', 'fixed'),
},
});
Dynamic styles
Defining styles as a function allows them to be dynamically calculated at runtime. The style function can accept the dynamic parts of the style as parameters. These styles cannot be optimized as effectively as static styles.
import { css, html } from 'react-strict-dom';
const styles = css.create({
size: (height: number, width: number) => ({
height * 0.9,
width
})
});
function MyComponent() {
const {height, width} = useContainerSize();
return <html.div style={styles.size(height, width))} />;
}
Inherited styles
Inheritance is the process by which elements inherit the the values of properties from their ancestors in the DOM tree. Some properties, e.g. color
, are automatically inherited by the children of the element to which they are applied. Each property defines whether it will be automatically inherited.
React Strict DOM currently only supports inheritance for text style properties on native (these style properties can be applied to any element.) The inherit
or unset
value can also be set for any of these properties to restore their default behavior.
Using styles
Once styles have been defined, they can be passed directly to the style
prop on html.*
elements.
import { css, html } from 'react-strict-dom';
const styles = css.create({
root: { ... }
});
const Foo = () => (
<html.div style={styles.root} />
);
Styles can be imported from other files and provided as props.
Merge styles
The style
prop can take a list of styles and merge them in a deterministic way.
The order in which the styles are defined does not affect the resulting styles, only the order in which they are applied to the HTML element.
import { css, html } from 'react-strict-dom';
const styles = css.create({
root: { ... }
});
const Foo = (props) => (
<html.div style={[ props.style, styles.root ]} />
);
Conditional styles
Styles can be conditionally applied using common JavaScript patterns, such as ternary expressions and the &&
operator. Falsy styles (i.e., null
, undefined
or false
) are ignored.
<html.div
style={[
styles.root,
props.isHighlighted && styles.highlighted,
isActive ? styles.active : styles.inactive,
]}
/>
Variant styles
A common styling pattern called "variants" allows styles to be set based on the value of props. This is easy to accomplish in React Strict DOM using object property lookups. This pattern can be combined with the conditional patterns to support arbitrarily complex logic for applying styles.
import { css, html } from 'react-strict-dom';
const colorVariantStyles = css.create({
red: {
color: 'rgb(200, 0, 0)',
},
green: {
color: 'rgb(0, 200, 0)',
}
});
const sizeVariantStyles = css.create({
small: {
fontSize: '0.75rem',
},
large: {
fontSize: '1.5rem',
}
});
export function Foo({ color, size, ...props }) {
return (
<html.span
{...props}
style={[
colorVariantStyles[color]
sizeVariantStyles[size]
]}
/>
)
}
Debugging styles
React Strict DOM includes some helpful debugging information for web in the DOM output when debug
is set to true
in the Babel preset. You may also find this Atomic CSS Devtools extension useful. On native, the React Native DevTools should be used.