React Native for Web is a comprehensive compatibility library that enables React Native components and APIs to run seamlessly on web browsers using React DOM.
—
React Native's styling system adapted for web with CSS-in-JS compilation, atomic CSS generation, RTL support, and comprehensive performance optimizations.
The main StyleSheet API that provides style creation, composition, and optimization utilities with automatic CSS generation and browser compatibility.
const StyleSheet: {
create: <T>(styles: T) => T;
flatten: (...styles: any[]) => ComputedStyle;
compose: (style1: any, style2: any) => any[];
absoluteFill: ViewStyle;
absoluteFillObject: ViewStyle;
hairlineWidth: number;
getSheet: () => { id: string, textContent: string };
};Core Methods:
Creates and optimizes style objects, generating atomic CSS classes for performance.
StyleSheet.create<T>(styles: T): TUsage:
import { StyleSheet } from "react-native-web";
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
padding: 20
},
header: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 16,
color: '#333'
},
button: {
backgroundColor: '#007AFF',
paddingHorizontal: 20,
paddingVertical: 12,
borderRadius: 8,
alignItems: 'center'
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: '600'
}
});
// Usage in components
function MyComponent() {
return (
<View style={styles.container}>
<Text style={styles.header}>Welcome</Text>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>Press me</Text>
</TouchableOpacity>
</View>
);
}
// Advanced patterns
const createThemedStyles = (theme) => StyleSheet.create({
container: {
backgroundColor: theme.backgroundColor,
flex: 1
},
text: {
color: theme.textColor,
fontSize: theme.fontSize
},
// Raw styles (no atomic compilation)
'gradient$raw': {
background: `linear-gradient(45deg, ${theme.primary}, ${theme.secondary})`
}
});Flattens an array of style objects into a single style object, resolving overrides and conflicts.
StyleSheet.flatten(...styles: any[]): ComputedStyleUsage:
// Flatten multiple styles
const baseStyle = { color: 'blue', fontSize: 16 };
const overrideStyle = { color: 'red' };
const flattenedStyle = StyleSheet.flatten([baseStyle, overrideStyle]);
console.log(flattenedStyle); // { color: 'red', fontSize: 16 }
// Conditional style flattening
function ConditionalComponent({ isActive, disabled }) {
const computedStyle = StyleSheet.flatten([
styles.base,
isActive && styles.active,
disabled && styles.disabled
]);
return <View style={computedStyle} />;
}
// Style composition utility
function createComposedStyle(...styleArrays) {
return StyleSheet.flatten(styleArrays.flat());
}Composes two styles into an array (deprecated, use array syntax instead).
StyleSheet.compose(style1: any, style2: any): any[]Usage:
// Deprecated approach
const composed = StyleSheet.compose(styles.base, styles.variant);
// Preferred approach
const composed = [styles.base, styles.variant];Pre-defined styles for absolute positioning that fills the parent container.
StyleSheet.absoluteFill: ViewStyle;
StyleSheet.absoluteFillObject: {
position: 'absolute';
left: 0;
right: 0;
top: 0;
bottom: 0;
};Usage:
// Using the pre-compiled style
<View style={StyleSheet.absoluteFill} />
// Using the object for composition
const overlayStyle = StyleSheet.create({
overlay: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(0,0,0,0.5)',
justifyContent: 'center',
alignItems: 'center'
}
});
// Custom absolute positioning
const customAbsolute = StyleSheet.create({
positioned: {
...StyleSheet.absoluteFillObject,
top: 50, // Override top
bottom: 50 // Override bottom
}
});The thinnest possible line width (always 1 on web).
StyleSheet.hairlineWidth: 1;Usage:
const styles = StyleSheet.create({
separator: {
height: StyleSheet.hairlineWidth,
backgroundColor: '#e0e0e0',
marginVertical: 8
},
border: {
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: '#ccc'
}
});Create responsive and conditional styles efficiently.
// Responsive styles
function createResponsiveStyles(screenWidth) {
const isTablet = screenWidth >= 768;
const isDesktop = screenWidth >= 1024;
return StyleSheet.create({
container: {
padding: isDesktop ? 32 : isTablet ? 24 : 16,
maxWidth: isDesktop ? 1200 : '100%',
marginHorizontal: isDesktop ? 'auto' : 0
},
grid: {
flexDirection: isTablet ? 'row' : 'column',
flexWrap: isTablet ? 'wrap' : 'nowrap'
}
});
}
// Theme-based styling
function createThemedStyles(isDark) {
return StyleSheet.create({
container: {
backgroundColor: isDark ? '#1a1a1a' : '#ffffff',
flex: 1
},
text: {
color: isDark ? '#ffffff' : '#000000'
},
surface: {
backgroundColor: isDark ? '#2d2d2d' : '#f8f9fa',
borderColor: isDark ? '#444' : '#e9ecef',
borderWidth: 1
}
});
}
// Usage with hooks
function ThemedComponent() {
const { width } = useWindowDimensions();
const isDark = useColorScheme() === 'dark';
const styles = useMemo(() => ({
...createResponsiveStyles(width),
...createThemedStyles(isDark)
}), [width, isDark]);
return (
<View style={styles.container}>
<Text style={styles.text}>Themed content</Text>
</View>
);
}Leverage atomic CSS and compilation for optimal performance.
// Atomic class generation
const atomicStyles = StyleSheet.create({
// Each property becomes an atomic class
flex1: { flex: 1 },
row: { flexDirection: 'row' },
column: { flexDirection: 'column' },
center: { alignItems: 'center', justifyContent: 'center' },
// Colors
primaryBg: { backgroundColor: '#007AFF' },
secondaryBg: { backgroundColor: '#34C759' },
// Spacing
p4: { padding: 16 },
m2: { margin: 8 },
mt3: { marginTop: 12 }
});
// Composition for complex layouts
const layoutStyles = StyleSheet.create({
centeredContainer: {
...atomicStyles.flex1,
...atomicStyles.center,
...atomicStyles.p4
}
});
// Raw styles for CSS that can't be atomized
const rawStyles = StyleSheet.create({
'gradient$raw': {
background: 'linear-gradient(45deg, #ff6b6b, #4ecdc4)'
},
'animation$raw': {
'@keyframes fadeIn': {
from: { opacity: 0 },
to: { opacity: 1 }
},
animation: 'fadeIn 0.3s ease-in-out'
}
});Handle right-to-left layouts automatically.
// RTL-aware styles
const rtlStyles = StyleSheet.create({
container: {
paddingStart: 16, // Becomes paddingLeft in LTR, paddingRight in RTL
paddingEnd: 8, // Becomes paddingRight in LTR, paddingLeft in RTL
marginStart: 12 // Auto-flips based on text direction
},
textAlign: {
textAlign: 'start' // Becomes 'left' in LTR, 'right' in RTL
}
});
// Manual RTL handling
function RTLAwareComponent() {
const isRTL = I18nManager.isRTL;
const styles = StyleSheet.create({
container: {
paddingLeft: isRTL ? 8 : 16,
paddingRight: isRTL ? 16 : 8,
flexDirection: isRTL ? 'row-reverse' : 'row'
}
});
return <View style={styles.container} />;
}Create reusable style generators and utilities.
// Style generator functions
const createShadow = (elevation = 2) => ({
shadowColor: '#000',
shadowOffset: {
width: 0,
height: elevation
},
shadowOpacity: 0.25,
shadowRadius: elevation * 2,
elevation // Android
});
const createBorder = (color = '#ccc', width = 1) => ({
borderColor: color,
borderWidth: width
});
// Usage in StyleSheet
const componentStyles = StyleSheet.create({
card: {
backgroundColor: 'white',
borderRadius: 8,
padding: 16,
...createShadow(3),
...createBorder('#e0e0e0')
},
button: {
paddingVertical: 12,
paddingHorizontal: 20,
borderRadius: 6,
...createShadow(1)
}
});
// Advanced composition utilities
class StyleBuilder {
constructor(baseStyle = {}) {
this.style = { ...baseStyle };
}
background(color) {
this.style.backgroundColor = color;
return this;
}
padding(value) {
this.style.padding = value;
return this;
}
shadow(elevation) {
Object.assign(this.style, createShadow(elevation));
return this;
}
build() {
return this.style;
}
}
// Usage
const dynamicStyle = new StyleBuilder()
.background('#007AFF')
.padding(16)
.shadow(2)
.build();Extract generated CSS for SSR applications.
// Get generated CSS
const sheet = StyleSheet.getSheet();
console.log(sheet.id); // CSS sheet ID
console.log(sheet.textContent); // Generated CSS content
// SSR implementation
function renderWithStyles(App) {
// Render app
const appHtml = ReactDOMServer.renderToString(<App />);
// Extract styles
const { id, textContent } = StyleSheet.getSheet();
// Include in HTML
return `
<!DOCTYPE html>
<html>
<head>
<style id="${id}">${textContent}</style>
</head>
<body>
<div id="root">${appHtml}</div>
</body>
</html>
`;
}// ✅ Good: Use StyleSheet.create
const styles = StyleSheet.create({
container: { flex: 1 }
});
// ❌ Avoid: Inline styles (no optimization)
<View style={{ flex: 1 }} />
// ✅ Good: Conditional styles with arrays
<View style={[
styles.base,
isActive && styles.active,
{ opacity: isVisible ? 1 : 0 }
]} />
// ✅ Good: Memoize dynamic styles
const dynamicStyles = useMemo(() => StyleSheet.create({
container: {
backgroundColor: theme.background
}
}), [theme]);
// ✅ Good: Use constants for reusable values
const COLORS = {
primary: '#007AFF',
secondary: '#34C759',
background: '#f8f9fa'
};
const SPACING = {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32
};
const styles = StyleSheet.create({
container: {
backgroundColor: COLORS.background,
padding: SPACING.md
}
});interface StyleSheetStatic {
create: <T extends Record<string, ViewStyle | TextStyle | ImageStyle>>(styles: T) => T;
flatten: (...styles: any[]) => ComputedStyle;
compose: (style1: any, style2: any) => any[];
absoluteFill: ViewStyle;
absoluteFillObject: {
position: 'absolute';
left: 0;
right: 0;
top: 0;
bottom: 0;
};
hairlineWidth: 1;
getSheet: () => { id: string; textContent: string };
}
interface ViewStyle {
// Layout
flex?: number;
flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse';
justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
// Positioning
position?: 'absolute' | 'relative' | 'static' | 'fixed' | 'sticky';
top?: number | string;
right?: number | string;
bottom?: number | string;
left?: number | string;
zIndex?: number;
// Dimensions
width?: number | string;
height?: number | string;
minWidth?: number | string;
maxWidth?: number | string;
minHeight?: number | string;
maxHeight?: number | string;
// Spacing
margin?: number | string;
marginTop?: number | string;
marginRight?: number | string;
marginBottom?: number | string;
marginLeft?: number | string;
marginHorizontal?: number | string;
marginVertical?: number | string;
padding?: number | string;
paddingTop?: number | string;
paddingRight?: number | string;
paddingBottom?: number | string;
paddingLeft?: number | string;
paddingHorizontal?: number | string;
paddingVertical?: number | string;
// Background
backgroundColor?: ColorValue;
// Border
borderWidth?: number;
borderTopWidth?: number;
borderRightWidth?: number;
borderBottomWidth?: number;
borderLeftWidth?: number;
borderColor?: ColorValue;
borderTopColor?: ColorValue;
borderRightColor?: ColorValue;
borderBottomColor?: ColorValue;
borderLeftColor?: ColorValue;
borderRadius?: number;
borderTopLeftRadius?: number;
borderTopRightRadius?: number;
borderBottomLeftRadius?: number;
borderBottomRightRadius?: number;
borderStyle?: 'solid' | 'dotted' | 'dashed';
// Shadow
shadowColor?: ColorValue;
shadowOffset?: { width: number; height: number };
shadowOpacity?: number;
shadowRadius?: number;
// Transform
transform?: Transform[];
// Other
opacity?: number;
overflow?: 'visible' | 'hidden' | 'scroll';
}
interface TextStyle extends ViewStyle {
color?: ColorValue;
fontFamily?: string;
fontSize?: number | string;
fontWeight?: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
fontStyle?: 'normal' | 'italic';
lineHeight?: number | string;
letterSpacing?: number | string;
textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify';
textDecorationLine?: 'none' | 'underline' | 'line-through' | 'underline line-through';
textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
}
interface ImageStyle extends ViewStyle {
resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';
tintColor?: ColorValue;
}
type ComputedStyle = { [key: string]: any };
type ColorValue = string;
type Transform = { [key: string]: any };Install with Tessl CLI
npx tessl i tessl/npm-react-native-web