CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-native-web

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.

Pending
Overview
Eval results
Files

stylesheet.mddocs/

StyleSheet

React Native's styling system adapted for web with CSS-in-JS compilation, atomic CSS generation, RTL support, and comprehensive performance optimizations.

StyleSheet

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:

create()

Creates and optimizes style objects, generating atomic CSS classes for performance.

StyleSheet.create<T>(styles: T): T

Usage:

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})`
  }
});

flatten()

Flattens an array of style objects into a single style object, resolving overrides and conflicts.

StyleSheet.flatten(...styles: any[]): ComputedStyle

Usage:

// 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());
}

compose()

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];

Constants

absoluteFill & absoluteFillObject

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
  }
});

hairlineWidth

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'
  }
});

Advanced Features

Dynamic Styling

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>
  );
}

Performance Optimization

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'
  }
});

RTL Support

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} />;
}

Custom Style Functions

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();

Server-Side Rendering

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>
  `;
}

Best Practices

// ✅ 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
  }
});

Types

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

docs

accessibility.md

animation.md

core-utilities.md

form-controls.md

hooks.md

index.md

interactive-components.md

layout-components.md

list-components.md

media-components.md

platform-apis.md

stylesheet.md

system-integration.md

text-input.md

tile.json