0
# StyleSheet
1
2
React Native's styling system adapted for web with CSS-in-JS compilation, atomic CSS generation, RTL support, and comprehensive performance optimizations.
3
4
## StyleSheet
5
6
The main StyleSheet API that provides style creation, composition, and optimization utilities with automatic CSS generation and browser compatibility.
7
8
```javascript { .api }
9
const StyleSheet: {
10
create: <T>(styles: T) => T;
11
flatten: (...styles: any[]) => ComputedStyle;
12
compose: (style1: any, style2: any) => any[];
13
absoluteFill: ViewStyle;
14
absoluteFillObject: ViewStyle;
15
hairlineWidth: number;
16
getSheet: () => { id: string, textContent: string };
17
};
18
```
19
20
**Core Methods:**
21
22
### create()
23
Creates and optimizes style objects, generating atomic CSS classes for performance.
24
25
```javascript { .api }
26
StyleSheet.create<T>(styles: T): T
27
```
28
29
**Usage:**
30
```javascript
31
import { StyleSheet } from "react-native-web";
32
33
const styles = StyleSheet.create({
34
container: {
35
flex: 1,
36
backgroundColor: '#f5f5f5',
37
padding: 20
38
},
39
header: {
40
fontSize: 24,
41
fontWeight: 'bold',
42
marginBottom: 16,
43
color: '#333'
44
},
45
button: {
46
backgroundColor: '#007AFF',
47
paddingHorizontal: 20,
48
paddingVertical: 12,
49
borderRadius: 8,
50
alignItems: 'center'
51
},
52
buttonText: {
53
color: 'white',
54
fontSize: 16,
55
fontWeight: '600'
56
}
57
});
58
59
// Usage in components
60
function MyComponent() {
61
return (
62
<View style={styles.container}>
63
<Text style={styles.header}>Welcome</Text>
64
<TouchableOpacity style={styles.button}>
65
<Text style={styles.buttonText}>Press me</Text>
66
</TouchableOpacity>
67
</View>
68
);
69
}
70
71
// Advanced patterns
72
const createThemedStyles = (theme) => StyleSheet.create({
73
container: {
74
backgroundColor: theme.backgroundColor,
75
flex: 1
76
},
77
text: {
78
color: theme.textColor,
79
fontSize: theme.fontSize
80
},
81
// Raw styles (no atomic compilation)
82
'gradient$raw': {
83
background: `linear-gradient(45deg, ${theme.primary}, ${theme.secondary})`
84
}
85
});
86
```
87
88
### flatten()
89
Flattens an array of style objects into a single style object, resolving overrides and conflicts.
90
91
```javascript { .api }
92
StyleSheet.flatten(...styles: any[]): ComputedStyle
93
```
94
95
**Usage:**
96
```javascript
97
// Flatten multiple styles
98
const baseStyle = { color: 'blue', fontSize: 16 };
99
const overrideStyle = { color: 'red' };
100
const flattenedStyle = StyleSheet.flatten([baseStyle, overrideStyle]);
101
console.log(flattenedStyle); // { color: 'red', fontSize: 16 }
102
103
// Conditional style flattening
104
function ConditionalComponent({ isActive, disabled }) {
105
const computedStyle = StyleSheet.flatten([
106
styles.base,
107
isActive && styles.active,
108
disabled && styles.disabled
109
]);
110
111
return <View style={computedStyle} />;
112
}
113
114
// Style composition utility
115
function createComposedStyle(...styleArrays) {
116
return StyleSheet.flatten(styleArrays.flat());
117
}
118
```
119
120
### compose()
121
Composes two styles into an array (deprecated, use array syntax instead).
122
123
```javascript { .api }
124
StyleSheet.compose(style1: any, style2: any): any[]
125
```
126
127
**Usage:**
128
```javascript
129
// Deprecated approach
130
const composed = StyleSheet.compose(styles.base, styles.variant);
131
132
// Preferred approach
133
const composed = [styles.base, styles.variant];
134
```
135
136
## Constants
137
138
### absoluteFill & absoluteFillObject
139
Pre-defined styles for absolute positioning that fills the parent container.
140
141
```javascript { .api }
142
StyleSheet.absoluteFill: ViewStyle;
143
StyleSheet.absoluteFillObject: {
144
position: 'absolute';
145
left: 0;
146
right: 0;
147
top: 0;
148
bottom: 0;
149
};
150
```
151
152
**Usage:**
153
```javascript
154
// Using the pre-compiled style
155
<View style={StyleSheet.absoluteFill} />
156
157
// Using the object for composition
158
const overlayStyle = StyleSheet.create({
159
overlay: {
160
...StyleSheet.absoluteFillObject,
161
backgroundColor: 'rgba(0,0,0,0.5)',
162
justifyContent: 'center',
163
alignItems: 'center'
164
}
165
});
166
167
// Custom absolute positioning
168
const customAbsolute = StyleSheet.create({
169
positioned: {
170
...StyleSheet.absoluteFillObject,
171
top: 50, // Override top
172
bottom: 50 // Override bottom
173
}
174
});
175
```
176
177
### hairlineWidth
178
The thinnest possible line width (always 1 on web).
179
180
```javascript { .api }
181
StyleSheet.hairlineWidth: 1;
182
```
183
184
**Usage:**
185
```javascript
186
const styles = StyleSheet.create({
187
separator: {
188
height: StyleSheet.hairlineWidth,
189
backgroundColor: '#e0e0e0',
190
marginVertical: 8
191
},
192
border: {
193
borderBottomWidth: StyleSheet.hairlineWidth,
194
borderBottomColor: '#ccc'
195
}
196
});
197
```
198
199
## Advanced Features
200
201
### Dynamic Styling
202
Create responsive and conditional styles efficiently.
203
204
```javascript
205
// Responsive styles
206
function createResponsiveStyles(screenWidth) {
207
const isTablet = screenWidth >= 768;
208
const isDesktop = screenWidth >= 1024;
209
210
return StyleSheet.create({
211
container: {
212
padding: isDesktop ? 32 : isTablet ? 24 : 16,
213
maxWidth: isDesktop ? 1200 : '100%',
214
marginHorizontal: isDesktop ? 'auto' : 0
215
},
216
grid: {
217
flexDirection: isTablet ? 'row' : 'column',
218
flexWrap: isTablet ? 'wrap' : 'nowrap'
219
}
220
});
221
}
222
223
// Theme-based styling
224
function createThemedStyles(isDark) {
225
return StyleSheet.create({
226
container: {
227
backgroundColor: isDark ? '#1a1a1a' : '#ffffff',
228
flex: 1
229
},
230
text: {
231
color: isDark ? '#ffffff' : '#000000'
232
},
233
surface: {
234
backgroundColor: isDark ? '#2d2d2d' : '#f8f9fa',
235
borderColor: isDark ? '#444' : '#e9ecef',
236
borderWidth: 1
237
}
238
});
239
}
240
241
// Usage with hooks
242
function ThemedComponent() {
243
const { width } = useWindowDimensions();
244
const isDark = useColorScheme() === 'dark';
245
246
const styles = useMemo(() => ({
247
...createResponsiveStyles(width),
248
...createThemedStyles(isDark)
249
}), [width, isDark]);
250
251
return (
252
<View style={styles.container}>
253
<Text style={styles.text}>Themed content</Text>
254
</View>
255
);
256
}
257
```
258
259
### Performance Optimization
260
Leverage atomic CSS and compilation for optimal performance.
261
262
```javascript
263
// Atomic class generation
264
const atomicStyles = StyleSheet.create({
265
// Each property becomes an atomic class
266
flex1: { flex: 1 },
267
row: { flexDirection: 'row' },
268
column: { flexDirection: 'column' },
269
center: { alignItems: 'center', justifyContent: 'center' },
270
271
// Colors
272
primaryBg: { backgroundColor: '#007AFF' },
273
secondaryBg: { backgroundColor: '#34C759' },
274
275
// Spacing
276
p4: { padding: 16 },
277
m2: { margin: 8 },
278
mt3: { marginTop: 12 }
279
});
280
281
// Composition for complex layouts
282
const layoutStyles = StyleSheet.create({
283
centeredContainer: {
284
...atomicStyles.flex1,
285
...atomicStyles.center,
286
...atomicStyles.p4
287
}
288
});
289
290
// Raw styles for CSS that can't be atomized
291
const rawStyles = StyleSheet.create({
292
'gradient$raw': {
293
background: 'linear-gradient(45deg, #ff6b6b, #4ecdc4)'
294
},
295
'animation$raw': {
296
'@keyframes fadeIn': {
297
from: { opacity: 0 },
298
to: { opacity: 1 }
299
},
300
animation: 'fadeIn 0.3s ease-in-out'
301
}
302
});
303
```
304
305
### RTL Support
306
Handle right-to-left layouts automatically.
307
308
```javascript
309
// RTL-aware styles
310
const rtlStyles = StyleSheet.create({
311
container: {
312
paddingStart: 16, // Becomes paddingLeft in LTR, paddingRight in RTL
313
paddingEnd: 8, // Becomes paddingRight in LTR, paddingLeft in RTL
314
marginStart: 12 // Auto-flips based on text direction
315
},
316
textAlign: {
317
textAlign: 'start' // Becomes 'left' in LTR, 'right' in RTL
318
}
319
});
320
321
// Manual RTL handling
322
function RTLAwareComponent() {
323
const isRTL = I18nManager.isRTL;
324
325
const styles = StyleSheet.create({
326
container: {
327
paddingLeft: isRTL ? 8 : 16,
328
paddingRight: isRTL ? 16 : 8,
329
flexDirection: isRTL ? 'row-reverse' : 'row'
330
}
331
});
332
333
return <View style={styles.container} />;
334
}
335
```
336
337
### Custom Style Functions
338
Create reusable style generators and utilities.
339
340
```javascript
341
// Style generator functions
342
const createShadow = (elevation = 2) => ({
343
shadowColor: '#000',
344
shadowOffset: {
345
width: 0,
346
height: elevation
347
},
348
shadowOpacity: 0.25,
349
shadowRadius: elevation * 2,
350
elevation // Android
351
});
352
353
const createBorder = (color = '#ccc', width = 1) => ({
354
borderColor: color,
355
borderWidth: width
356
});
357
358
// Usage in StyleSheet
359
const componentStyles = StyleSheet.create({
360
card: {
361
backgroundColor: 'white',
362
borderRadius: 8,
363
padding: 16,
364
...createShadow(3),
365
...createBorder('#e0e0e0')
366
},
367
button: {
368
paddingVertical: 12,
369
paddingHorizontal: 20,
370
borderRadius: 6,
371
...createShadow(1)
372
}
373
});
374
375
// Advanced composition utilities
376
class StyleBuilder {
377
constructor(baseStyle = {}) {
378
this.style = { ...baseStyle };
379
}
380
381
background(color) {
382
this.style.backgroundColor = color;
383
return this;
384
}
385
386
padding(value) {
387
this.style.padding = value;
388
return this;
389
}
390
391
shadow(elevation) {
392
Object.assign(this.style, createShadow(elevation));
393
return this;
394
}
395
396
build() {
397
return this.style;
398
}
399
}
400
401
// Usage
402
const dynamicStyle = new StyleBuilder()
403
.background('#007AFF')
404
.padding(16)
405
.shadow(2)
406
.build();
407
```
408
409
## Server-Side Rendering
410
411
Extract generated CSS for SSR applications.
412
413
```javascript
414
// Get generated CSS
415
const sheet = StyleSheet.getSheet();
416
console.log(sheet.id); // CSS sheet ID
417
console.log(sheet.textContent); // Generated CSS content
418
419
// SSR implementation
420
function renderWithStyles(App) {
421
// Render app
422
const appHtml = ReactDOMServer.renderToString(<App />);
423
424
// Extract styles
425
const { id, textContent } = StyleSheet.getSheet();
426
427
// Include in HTML
428
return `
429
<!DOCTYPE html>
430
<html>
431
<head>
432
<style id="${id}">${textContent}</style>
433
</head>
434
<body>
435
<div id="root">${appHtml}</div>
436
</body>
437
</html>
438
`;
439
}
440
```
441
442
## Best Practices
443
444
```javascript
445
// ✅ Good: Use StyleSheet.create
446
const styles = StyleSheet.create({
447
container: { flex: 1 }
448
});
449
450
// ❌ Avoid: Inline styles (no optimization)
451
<View style={{ flex: 1 }} />
452
453
// ✅ Good: Conditional styles with arrays
454
<View style={[
455
styles.base,
456
isActive && styles.active,
457
{ opacity: isVisible ? 1 : 0 }
458
]} />
459
460
// ✅ Good: Memoize dynamic styles
461
const dynamicStyles = useMemo(() => StyleSheet.create({
462
container: {
463
backgroundColor: theme.background
464
}
465
}), [theme]);
466
467
// ✅ Good: Use constants for reusable values
468
const COLORS = {
469
primary: '#007AFF',
470
secondary: '#34C759',
471
background: '#f8f9fa'
472
};
473
474
const SPACING = {
475
xs: 4,
476
sm: 8,
477
md: 16,
478
lg: 24,
479
xl: 32
480
};
481
482
const styles = StyleSheet.create({
483
container: {
484
backgroundColor: COLORS.background,
485
padding: SPACING.md
486
}
487
});
488
```
489
490
## Types
491
492
```javascript { .api }
493
interface StyleSheetStatic {
494
create: <T extends Record<string, ViewStyle | TextStyle | ImageStyle>>(styles: T) => T;
495
flatten: (...styles: any[]) => ComputedStyle;
496
compose: (style1: any, style2: any) => any[];
497
absoluteFill: ViewStyle;
498
absoluteFillObject: {
499
position: 'absolute';
500
left: 0;
501
right: 0;
502
top: 0;
503
bottom: 0;
504
};
505
hairlineWidth: 1;
506
getSheet: () => { id: string; textContent: string };
507
}
508
509
interface ViewStyle {
510
// Layout
511
flex?: number;
512
flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse';
513
justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
514
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
515
516
// Positioning
517
position?: 'absolute' | 'relative' | 'static' | 'fixed' | 'sticky';
518
top?: number | string;
519
right?: number | string;
520
bottom?: number | string;
521
left?: number | string;
522
zIndex?: number;
523
524
// Dimensions
525
width?: number | string;
526
height?: number | string;
527
minWidth?: number | string;
528
maxWidth?: number | string;
529
minHeight?: number | string;
530
maxHeight?: number | string;
531
532
// Spacing
533
margin?: number | string;
534
marginTop?: number | string;
535
marginRight?: number | string;
536
marginBottom?: number | string;
537
marginLeft?: number | string;
538
marginHorizontal?: number | string;
539
marginVertical?: number | string;
540
padding?: number | string;
541
paddingTop?: number | string;
542
paddingRight?: number | string;
543
paddingBottom?: number | string;
544
paddingLeft?: number | string;
545
paddingHorizontal?: number | string;
546
paddingVertical?: number | string;
547
548
// Background
549
backgroundColor?: ColorValue;
550
551
// Border
552
borderWidth?: number;
553
borderTopWidth?: number;
554
borderRightWidth?: number;
555
borderBottomWidth?: number;
556
borderLeftWidth?: number;
557
borderColor?: ColorValue;
558
borderTopColor?: ColorValue;
559
borderRightColor?: ColorValue;
560
borderBottomColor?: ColorValue;
561
borderLeftColor?: ColorValue;
562
borderRadius?: number;
563
borderTopLeftRadius?: number;
564
borderTopRightRadius?: number;
565
borderBottomLeftRadius?: number;
566
borderBottomRightRadius?: number;
567
borderStyle?: 'solid' | 'dotted' | 'dashed';
568
569
// Shadow
570
shadowColor?: ColorValue;
571
shadowOffset?: { width: number; height: number };
572
shadowOpacity?: number;
573
shadowRadius?: number;
574
575
// Transform
576
transform?: Transform[];
577
578
// Other
579
opacity?: number;
580
overflow?: 'visible' | 'hidden' | 'scroll';
581
}
582
583
interface TextStyle extends ViewStyle {
584
color?: ColorValue;
585
fontFamily?: string;
586
fontSize?: number | string;
587
fontWeight?: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
588
fontStyle?: 'normal' | 'italic';
589
lineHeight?: number | string;
590
letterSpacing?: number | string;
591
textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify';
592
textDecorationLine?: 'none' | 'underline' | 'line-through' | 'underline line-through';
593
textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
594
}
595
596
interface ImageStyle extends ViewStyle {
597
resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';
598
tintColor?: ColorValue;
599
}
600
601
type ComputedStyle = { [key: string]: any };
602
type ColorValue = string;
603
type Transform = { [key: string]: any };
604
```